最近被尋路給搞蒙了,由於我想做汽車的尋路,而且汽車速度什麼的都定義好了,而unity自帶的組件nav mesh agent自帶了一些速度之類的值,搞得我很不開心,雖然值可以設爲0,但後來還是發現有很多問題。不過,這個自帶的功能還是很不錯,可能不適合汽車,只對人比較友好,本着學習的態度我認真研究了一下。
我們都知道,unity常見的尋路算法有:Astar尋路,自帶尋路navmesh,點尋路等等。A*尋路就不說了,早期一般都是用它,算法插件網上都有。unity自帶的這個尋路很有意思,首先選擇window->navigation,然後可以看到檢視板後面多了一個,選擇你要烘培的靜態物體,一般是地面,道路等等。勾選navigation static,烘培bake意思是被你選擇的地方是可通行的,當然注意下面navigation area,裏面有walkable,還有not walkable。勾選完之後就可以點擊bake了,還有一些參數啥的,可以在API上去查查,可以多次bake哦。成功之後你可通行區域變成這個樣子,可以看到變成了淺藍色。
然後你需要在尋路者的身上掛一個Nev mesh agent組件,如圖:
看到左上角那個人了嗎,不是我要吐槽它啊,可能就是爲主角是人量身定製的,它是一個膠囊體,注意的是你需要調radius和height把尋路物體完全包住。然後設置一個尋路對象就可以尋路了,是不是很簡單。自帶的組件還有一個重要功能就是動態尋路,動態尋路意思是你在尋路的過程中突然增加了一個障礙,遊戲中很常見的。具體做法是在上面基礎上,給障礙物添加一個組件nav mesh obstacle,再掛一個剛體,製作成預製體(就是可以複用的東西),然後把它做成一個在運行時動態Instantiate 實例化出來,尋路網格會重新生成。具體運行時這些組件幫你找到一條最短路徑然後動態避障。當然還有一些別的運用,比如三路小兵分別尋不同的路徑。
網上看資料的時候發現一位童鞋的例子特別好,值得好好學習。傳送門~還有動態避障再傳送,還有小兵這個,好像他也是轉的,在這裏,感謝各位大佬。
然後點尋路官方的例子有,但是我感覺太過複雜,後來自己寫了一個很菜的方法,就是汽車一個位置一個位置的去尋,意思我提前定好位置,它只需要一個一個去找就好了。如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System;
namespace UnityStandardAssets.Vehicles.Car
{
[RequireComponent(typeof(CarAIControl))]
[RequireComponent(typeof(CarController))]
public class WayTrack : MonoBehaviour
{
public GameObject obj;
public Transform[] newposition = new Transform[] { };
int k = 0;
float dis;
// Use this for initialization
void Start()
{
obj.transform.position = newposition[0].position;
}
// Update is called once per frame
void Update()
{
Vector3 m = obj.transform.position;
Vector3 n = this.transform.position;
dis = Vector3.Distance(m, n);
if (dis < 2.0f)
{
k++;
k = k % newposition.Length;
Transform next = newposition[k];
obj.transform.position = next.position;
Quaternion shipRotation = Quaternion.Euler(0, 0, 0);
obj.transform.rotation = shipRotation;
// Debug.Log(k);
}
Debug.Log(GetComponent<CarController>().m_Rigidbody.velocity.magnitude*3.6f);
}
void OnTriggerEnter(Collider other)
{
// GetComponent<CarAIControl>(). m_CarController.Move(0, 0, -1f, 1f);
if (other.tag == "stop"&&dis<10)
{
GetComponent<CarAIControl>().m_Driving = false;
}
else
{
GetComponent<CarAIControl>().m_Driving = true;
}
}
}
}
這個和我前面翻譯的官方例子是一個系列,可以看出我update中每幀都在計算它與下一個位置的距離,當小於2時,目標位置會跳到下一個位置。然後添加了接觸器,當接觸到tag是stop的物體且dis小於10,汽車會剎車。後續還會有很多功能,我會一一分享。