簡介
效能優化的方法有百百種,但有些方法都只會有些微優化成果,要解決就要從源頭解決。不知道大家有沒有在玩線上遊戲時遇過在大地圖移動時,在較遠的物件會比較模糊或是消失,等到與腳色距離縮小時才會顯得特別明顯。
而在 Unity3D 中也是有類似的方法,例如使用 LOD Group,但距離遠到 Culling 的階段時該物件還是 Active 的,而假使場景中物件太多也會造成系統的壓力,降低很多 FPS。
因此我們這篇想要運用線上遊戲的物件顯示方式並不使用Unity3D LOD Grop且到限定距離外將物件消失,使用到Collider Trigger。
距離測試
在講到Collider Trigger前,先說說兩物件中的距離偵測(如下圖,在三度空間的算法Unity只要一個函式就解決,但讓大家知道空間距離運算的概念圖);其實距離偵測是最準確的方式,假如物件不多其實可以考慮使用此方法,但物件一多則CPU每禎運算Update會耗太多資源,所以Collider就是最好的方法。
實驗
首先我們要準備實驗材料
- 碰撞者
- 被碰撞者
- 自動生成好多的被碰撞者
碰撞者,在實驗過程中你可以自己操控位移的程式,控制腳色方面這邊就不多說了,但在碰撞者的身上你要掛上Trigger的程式並且設定Collider。
Collider你可以自己選用種類,Box , Mesh , Capsule等等,而尺寸大小就看你要顯示的範圍要多大,我這邊就設定50。
Collider Trigger程式碼,我們在MonoBehaviour不需要Start與Update可以刪掉,這邊只需要OnTrigger系列程式碼。在Unity Document中有詳細的介紹,如下圖。而我們會使用到的方法為紅色框框處。
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.GetComponent<MeshRenderer>().enabled != true)
{
other.gameObject.GetComponent<MeshRenderer>().enabled = true;
}
}
private void OnTriggerExit(Collider other)
{
if (other.gameObject.GetComponent<MeshRenderer>().enabled != false)
{
other.gameObject.GetComponent<MeshRenderer>().enabled = false;
}
}
這邊我們使用碰撞者與被碰撞者的 ColliderTrigger,當碰撞者進入到被碰撞者的 Collider 時就會觸發,使用 OnTriggerEnter;而離開則反之使用OnTriggerExit,當然你想要有更多的程序在兩個碰撞者持續碰撞期間有所作為就可以使用OnTriggerStay。
而 OnTriggerEnter(Collider other)中的Collider類別other物件,是可以抓取到被碰撞者的細部資訊,在本篇我們只要當碰撞到後就持續顯示,離開就消失,所以只要在 OnTriggerEnter / OnTriggerExit函式中控制other的SetActive(Ture) / SetActive(false) 即可。
被碰撞者,我們拿 Free 的 SpeedTree 套件來當作被碰撞者,選定某棵樹之後把它賦予 MeshCollider,並且要記得把 Is Trigger 打勾,這樣與碰撞者碰撞後才會有反應。
自動生成被碰撞者,以下為自動生成物件的主要方法較做 Instanitate(),其中需要幾個參數,要生成的GameObject樣本、生成的位置 Vector3()、生成的角度Quaternion。
Instantiate(genObject, new Vector3(Random.Range(-randomRange, randomRange), 1, Random.Range(-randomRange, randomRange)),Quaternion.identity)
實驗結果
小結
如下圖所示,我們同樣都自動隨機生成一萬個物件在 Unity 中,先不管被生成物件的材質、模型面數,假如不用本篇章所使用的 Collider Trigger,FPS會降低到8.4、Batches則會高達7027;然而使用後當然同時顯示的物件會減少,而這會反映到 FPS 與 Batches 上。而實際展示實驗成果如上影片,FPS還可以更高,大家就靈活運用在大型場景中了。