Unity3D 利用character controller控制人物在場景中移動和利用Navmesh Agent設定人物自動尋路
阿新 • • 發佈:2018-12-31
考慮碰撞的情況下控制人物的行走
在考慮碰撞的情況下,控制人物在場景中移動一般有兩種方法,一種是利用剛體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的,所以要把這個過程的特判一下,不然有可能會出現尋路的時候站在原地不動的情況。