滑鼠點擊地板的人物移動或3D與2D射線中提到的射線(Ray)。
Unity導航系統前三篇。
Mecanim動畫系統Part1、Part3、Part4。
本文開始。
這次要做的是,使用滑鼠點擊地板的人物移動操控。
移動路徑規劃使用導航網格(NavMesh),移動目標位置使用射線(Ray)指定,人物動畫則是使用Mecanim動畫系統。
成果如下圖。
在開始實作目標之前,需要先把物件準備好,第一個是地板物件Floor。
使用Plane物件,新增tag命名為Floor並且選取,接著點擊Static下拉選單,選取Navigation Static。
接著是障礙物物件Obstacle。
使用Cube物件,新增tag命名為Obstacle並且選取,新增元件Nav Mesh Obstacle,然後勾選Carve選項。
最後是人物模型。
這裡使用UnityChan的人物模型,在模型下新增元件Nav Mesh Agent。
將地板、障礙物和人物模型都準備好後,就可以開始實作這次的目標。
第一步是產生導航網格(NavMesh),Window -> Navigation開啟導航視窗,點選Bake,也就是烘焙生成導航網格。
如果場景沒存檔,Unity會告訴你要存檔。
烘焙(Bake)完成後,可以在場景中看到藍色的網格,如下圖。
接著點選人物模型,新增控制用腳本,腳本內容如下。
using UnityEngine;
public class Move : MonoBehaviour {
private NavMeshAgent agent;////(1)
private Vector3 target;
void Start () {
agent = GetComponent<NavMeshAgent>();////(2)
target = transform.position;
}
void Update () {
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);////(3)
RaycastHit hit;
if (Input.GetMouseButtonDown(0) ////(4)
&& Physics.Raycast(ray, out hit)
&& hit.transform.gameObject.tag == "Floor")
{
target = hit.point;////(5)
}
agent.SetDestination(target);////(6)
}
}
(1)腳本中有兩個重要變數,target負責記錄滑鼠點擊的位置,agent抓取target位置後移動。(2)在Start初始化時,agent抓取模型下的元件,target設定目標位置,這裡就給它模型位置作為初始化的數值。
(3)取得攝影機到滑鼠位置的射線。
(4)當滑鼠點擊左鍵時 & 射線有打到物體 & 該物體的標籤為Floor時,判斷式成立。
(5)將target位置設定為點擊的位置。
(6)將agent的目標設為target。
執行後點擊地板,應該可以看到以下結果。
到這裡會依照點擊的位置移動,而且帶有迴避障礙物的功能,移動的的部分就算是完成了。
最後追加人物的動畫當作修飾,讓Unity醬動起來好看一點。
在模型下新增元件Animator,並且在專案中新增Animator Controller檔案後代入Animator元件。
選取Window -> Animator,或雙擊Animator Controller檔案開啟動畫編輯視窗,接著將準備好的動畫,待機與移動拖曳至動畫編輯視窗。
在動畫上右鍵選取Make Transition,建立兩個動畫之間的轉換,然後在Parameters中新增浮點數speed。
選取轉換的線,將Has Exit Time的勾選取消,Conditions新增動畫轉換的門檻,待機到移動為大於(Greater),移動到待機為小於(Less),數值這裡設定為0.01。
開啟人物模型的控制腳本,加入紅字的程式碼。
using UnityEngine;
public class Move : MonoBehaviour {
private NavMeshAgent agent;
private Vector3 target;
private Animator animator;
void Start () {
agent = GetComponent<NavMeshAgent>();
target = transform.position;
animator = GetComponent<Animator>();
}
void Update () {
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Input.GetMouseButtonDown(0)
&& Physics.Raycast(ray, out hit)
&& hit.transform.gameObject.tag == "Floor")
{
target = hit.point;
}
agent.SetDestination(target);
animator.SetFloat("speed", agent.velocity.sqrMagnitude);
}
}
以下是執行結果。嗯‧‧‧有移動太快旋轉太慢的問題,將agent元件的參數Speed調整為2,Angular Speed調整為360。
再執行一次看看結果。
看起來好多了,以上就是加上導航網格的點擊地板移動,和先前相比,透過導航網格可以做出非直線的移動,同時也多了迴避障礙物的功能。
這次就到這裡。
素材連結:
Unity醬~~
以及‧‧‧
地板














沒有留言:
張貼留言