1. 程式人生 > >Unity3D 利用character controller控制人物在場景中移動和利用Navmesh Agent設定人物自動尋路

Unity3D 利用character controller控制人物在場景中移動和利用Navmesh Agent設定人物自動尋路

考慮碰撞的情況下控制人物的行走

在考慮碰撞的情況下,控制人物在場景中移動一般有兩種方法,一種是利用剛體Rigidbody,然後通過施加力或者改變速度來控制人物的移動,另外一種方法就是利用unity自帶的character controller來方便的呼叫函式直接控制行走。
由於character controller內部好像自帶類似於剛體的屬性,所以使用這個元件的話就不需要新增剛體了。當然膠囊體碰撞器Capsule Collider還是需要的。
首先新增Capsule Collider元件,根據自己人物模型的大小調整好碰撞器的高度、半徑以及中心,然後新增character controller元件,根據Capsule Collider來調整它高度、半徑以及中心。
如圖:這裡寫圖片描述


然後在人物上新增指令碼:

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<CharacterController>(); anim = this.GetComponent<Animator>(); } private void Update() { float h = Input.GetAxis("Horizontal"); float v = Input.GetAxis("Vertical"); if (Mathf.Abs(h) > 0.01
f || 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,這樣就可以了。
這裡寫圖片描述
這裡寫圖片描述

新增Navmesh Agent元件,同樣的,根據膠囊體碰撞器調整半徑和高度。
這裡寫圖片描述

新增指令碼:

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<NavMeshAgent>();
        anim = this.GetComponent<Animator>();
    }

    // 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的,所以要把這個過程的特判一下,不然有可能會出現尋路的時候站在原地不動的情況。