Unity3D 利用character controller控制人物在场景中移动和利用Navmesh Agent设置人物自动寻路

考虑碰撞的情况下控制人物的行走

在考虑碰撞的情况下,控制人物在场景中移动一般有两种方法,一种是利用刚体Rigidbody,然后通过施加力或者改变速度来控制人物的移动,另外一种方法就是利用unity自带的character controller来方便的调用函数直接控制行走。
由于character controller内部好像自带类似于刚体的属性,所以使用这个组件的话就不需要添加刚体了。当然胶囊体碰撞器Capsule Collider还是需要的。
首先添加Capsule Collider组件,根据自己人物模型的大小调整好碰撞器的高度、半径以及中心,然后添加character controller组件,根据Capsule Collider来调整它高度、半径以及中心。
如图:Unity3D 利用character controller控制人物在场景中移动和利用Navmesh Agent设置人物自动寻路_第1张图片
然后在人物上添加脚本:

using UnityEngine;
using System.Collections;

public class PlayerVillageMove : MonoBehaviour {
    // 设置成单例模式,便于调用
    public static PlayerVillageMove _instance; 
    // 角色控制器
    CharacterController controller;
    // 动画
    private Animator anim;
    // 移动速度
    public float speed = 0.3f;
    private void Awake() {
        _instance = this;
        controller = this.GetComponent();
        anim = this.GetComponent();
    }
    private void Update() {
        float h = Input.GetAxis("Horizontal");
        float v = Input.GetAxis("Vertical");
        if (Mathf.Abs(h) > 0.01f || Mathf.Abs(v) > 0.01f) {
            // 打开奔跑动画
            anim.SetBool("Move", true);
            // 这里旋转人物使他朝向我们想移动的方向
            transform.rotation = Quaternion.LookRotation(new Vector3(-h, 0, -v));
            Vector3 movedir = new Vector3(-h, -20, -v);
            // 用角色控制器让他移动
            controller.Move(movedir * speed);
        } else {
            // 切换到静止动画
            anim.SetBool("Move", false);
        }
    }
}

这样人物就可以通过wsad控制人物的行走了。

利用Navmesh Agent设置人物自动寻路

上面实现了人物的控制行走,下面来实现人物的自动寻路,这里使用unity自带的Navmesh Agent插件。
首先需要烘焙一下场景:

把地图和和所有的障碍物全选起来,在inspector面板上勾选static(要保证navigation staitic被勾选)。
这里写图片描述

随后点击菜单栏的window,选择Naviation,再选择bake,这样就可以了。
Unity3D 利用character controller控制人物在场景中移动和利用Navmesh Agent设置人物自动寻路_第2张图片
Unity3D 利用character controller控制人物在场景中移动和利用Navmesh Agent设置人物自动寻路_第3张图片

添加Navmesh Agent组件,同样的,根据胶囊体碰撞器调整半径和高度。
Unity3D 利用character controller控制人物在场景中移动和利用Navmesh Agent设置人物自动寻路_第4张图片

添加脚本:

using UnityEngine;
using System.Collections;

public class PlayerAutoMove : MonoBehaviour {

    private NavMeshAgent agent;
    public float minDistance = 3f;
    public Transform target;
    private Animator anim;

    private void Awake() {
        agent = this.GetComponent();
        anim = this.GetComponent();
    }

    // Update is called once per frame
    void Update () {
        if (Input.GetKeyDown(KeyCode.K)) {
            SetDestination(target.position);
        }
        if (agent.enabled) {
            // 这里要注意特判一下等于0的情况
            if (agent.remainingDistance != 0 && agent.remainingDistance < minDistance) {
                agent.Stop();
                agent.enabled = false;
                PlayerVillageMove._instance.enabled = true;
                anim.SetBool("Move", false);
            }
        }
    }

    public void SetDestination(Vector3 targetPos) {
        // 寻路的时候把键盘控制行走的脚本屏蔽掉
        PlayerVillageMove._instance.enabled = false;
        agent.enabled = true;
        anim.SetBool("Move", true);
        agent.SetDestination(targetPos);

    }
}

上面代码中在agent.remainingDistance上要特判一下等于0的情况,这是因为在SetDestination之后,会有一个计算路径的过程,在这个过程中agent.remainingDistance是被默认为0的,所以要把这个过程的特判一下,不然有可能会出现寻路的时候站在原地不动的情况。

你可能感兴趣的:(unity学习)