Unity全面入門筆記7-瞭解GameObject(1)

深入瞭解GameObject

創建GameObject

前面說到,GameObject必須存在於一個場景中。在場景中創造遊戲對象的方法有:

在Hierarchy面板中使用Create命令創建新物體。

將導入工程的模型文件、圖片文件和音樂文件從Project面板直接拖入場景創建對應的物體。

將Prefabs拖進場景創建物體。

在腳本中獲取gameObject

可以在腳本類中使用gameObject屬性來訪問該組件所附加在的GameObject實例。

新建一個名爲PrintGameObject的cs腳本,將PrintGameObject類的內容仿照如下代碼進行修改,然後將這個腳本附加在任意一個GameObject上,運行試玩,可以觀察到Console面板輸出的內容中包含這個腳本所附加的GameObject的名字。

class PrintGameObject : MonoBehavior
{
	void Start()
	{
		Debug.LogFormat("Hello {0}!",gameObject);
	}
}

GameObject的屬性

選中一個GameObject後,可以在Inspector面板中訪問GameObject的屬性:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Gd71GmAC-1569681761193)(C:\Users\UPiracy\AppData\Roaming\Typora\typora-user-images\1568340393530.png)]

  • 圖標

點擊左側的白色圖標可以更改GameObject的顯示圖標,這個圖標只在編譯器中生效,不會被打包。

  • Active

圖標選項右側的勾選框,對應gameObject對象的activeSelf屬性,控制物體的渲染和邏輯運作。當activeSelf == false時,該GameObject及其所有子物體都不會被渲染,都不再計算物理和碰撞,都不再運行附加其上的腳本,不再運行協程中的代碼,但會繼續運行Invoke中的代碼。

在腳本中activeSelf屬性是隻讀的,我們可以使用SetActive函數來改變這個屬性:

public bool GameObject.activeSelf{get; private set;}
public void GameObject.SetActive(bool active);
class PrintGameObject : MonoBehavior
{
	void Start()
 	{
 		if(gameObject.activeSelf)
 		{
 			gameObject.SetActive(flase);
 			Debug.LogFormat("The active is {0}.", gameObject, gameObject.activeSelf);
 		}
 	}
}

Unity處理activeSelf的邏輯是:每幀開始前檢測物體的activeSelf屬性,如果爲false則跳過這次幀週期的邏輯運算。所以,在代碼中使用SetActive將該屬性改爲false並不會導致代碼運行中斷,而會等到下一幀開始時才生效。因此運行上面的腳本時,LogFormat並不會因爲activeSelf == false而不被運行。

  • Name

Active右側的輸入框,對應GameObject的name屬性。使用Debug.Log輸出GameObject時,實際輸出的就是GameObject.name。name的用處除了在Hierarchy中命名方便管理外,還可以用於GameObject的查找,在場景中新建一個空物體改名爲"Empty",再新建一個空物體改名爲"Manager",將下方的腳本附加到Manager上,觀察結果。

string GameObject.name{get;set;}
GameObject GameObject.Find(string name);
class PrintGameObject : MonoBehavior
{
 	void Start()
 	{
 		GameObjcet empty = GameObjcet.Find("Empty");
 		if(empty == null)
 		{
 			Debug.LogError("We can't find any GameObjcet named \"Empty\"! ");
 		}
 		else
 		{
 			empty.name = "NewName";
 			Debug.Log("The name of what we find has changed to {0}!", empty);
 		}
 	}
}

衆所周知,判別String的算法的時間複雜度爲O(n),Find方法將遍歷整個Hierarchy並消耗大量的資源,所以儘量使用直接傳值的方式獲取需要的GameObject。

  • Static

Name右側的選項組。該選項組選擇爲Everything時選框顯示爲鉤號,當選擇了部分選項時顯示爲減號,當沒有選擇任何選項時選框爲空。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-K9Fk4EPm-1569681761194)(C:\Users\UPiracy\AppData\Roaming\Typora\typora-user-images\1568343835163.png)]

該選項組可以控制GameObject在渲染或烘培流程中的一些行爲:

Contribute GI:選中時使物體接收環境光並通過漫反射提供全局光照。

Occluder Static:將物體設置爲"遮擋物",當這個物體將某個"被遮擋物"遮擋時(從攝像機角度觀察,"被遮擋物"在"遮擋物"後面),讓被遮擋物從場景中剔除,效果跟Active爲False的時候一致。

Occludee Static:將物體設置爲"被遮擋物"。物體可以既是遮擋物又是被遮擋物。

舉個例子,假如A B C三個立方體,排成一列, 攝像機在A的正前方,從攝像機的視角中看不到B和C,因爲它倆被A擋住了。
如果這時候A是“遮擋物”,B和C是“被遮擋物”。那B和C就不會顯示在場景中(不僅是攝像機看不見,而是完全不在場景中出現)。
但如果攝像機穿過A,而移動到B的正前方,B和C都會顯示。因爲B是“被遮擋物”,卻沒有被“遮擋物”擋住(此時作爲遮擋物的A,在攝像機背面,並沒有擋住B).
那C爲何會顯示呢?因爲B只是“被遮擋物”,而不是“遮擋物”,所以它無法遮擋C。攝像機裏看不到C,但C依然會顯示在場景中。
如果此時把B同時勾選爲“遮擋物”。那麼C就不會顯示了。

Batching Static:將物體加入靜態批處理隊列。GameObject的渲染分爲CPU的draw call和GPU的裁剪變形等,如果CPU的draw call數量過多,會出現GPU等待CPU的情況。使用批處理後,在加載該場景的時候,Unity將使用相同材質的物體合併成一個更大的網格來進行draw call,使draw call的效率提升。這個方法是犧牲空間複雜度來滿足時間的方法,將導致在加載場景的時候消耗4倍的內存。

注:靜態批處理的方法還有在遊戲導出的時候,在player setting中勾選static batching,可以在編譯階段預先進行批處理,這樣導出來的包就會比較大,但卻不會導致額外內存。

Navigation Static:勾選後表示該對象參與AI尋路導航網格的烘培。這個設置將在AI章節中重點解釋。

Off Mesh Link Generation:勾選這個選項來自動計算AI尋路導航網路中的超網格鏈接。這個設置也將在AI章節中講述。

注:所謂超網格鏈接,是在兩個網格間並不直接相連的情況下,讓尋路AI額外考慮的節點:比如兩個平面佈置了尋路網絡,但兩個平面間存在一定間隙,正常情況下在平面A上的AI無法通過尋路前往平面B,但佈置一個超網格鏈接,並設置鏈接類型爲"跳躍間隙"後,就可以讓AI考慮跳過間隙前往平面B。

Reflection Probe Static:提供靜態反射信息,只有勾選這個選項的物體才能被鏡面反射。這個設置將在光照章節中講述。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章