Unity3D指令碼中Start()和Awake()的區別對比分析
初學者經常把Awake和Start混淆。
簡單說明一下,Awake在MonoBehavior建立後就立刻呼叫,Start將在MonoBehavior建立後在該幀Update之前,在該Monobehavior.enabled == true的情況下執行。
void Awake (){
}
//初始化函式,在遊戲開始時系統自動呼叫。一般用來建立變數之類的東西。
void Start(){
}
//初始化函式,在所有Awake函式執行完之後(一般是這樣,但不一定),在所有Update函式前系統自動條用。一般用來給變數賦值。
我們通常書寫的指令碼,並不會定義[ExecuteInEditMode]這個Attribute,所以Awake和Start都只有在Runtime中才會執行
例1:
public class Test : MonoBehaviour {
void Awake () {
Debug.Log("Awake");
enabled = false;
}
void Start () {
Debug.Log("Start");
}
}
以上程式碼,在Awake中我們呼叫了enabled = false; 禁止了這個MonoBehavior的update。由於Start, Update, PostUpdate等屬於runtime行為的一部分,這段程式碼將使Start不會被呼叫到。
在遊戲過程中,若有另外一組程式碼有如下呼叫:
Test test = go.GetComponent<Test>();
test.enabled = true;
這個時候,若該MonoBehavior之前並沒有觸發過Start函式,將會在這段程式碼執行後觸發。
例2:
player.cs
private Transform handAnchor = null;
void Awake () { handAnchor = transform.Find("hand_anchor"); }
// void Start () { handAnchor = transform.Find("hand_anchor"); }
void GetWeapon ( GameObject go ) {
if ( handAnchor == null ) {
Debug.LogError("handAnchor is null");
return;
}
go.transform.parent = handAnchor;
}
other.cs
GameObject go = new GameObject("player");
player pl = go.AddComponent<player>(); // Awake invoke right after this!
pl.GetWeapon(weaponGO);
...
以上程式碼中,我們在player Awake的時候去為handAnchor賦值。如果我們將這步操作放在Start裡,那麼在other.cs中,當執行GetWeapon的時候就會出現handAnchor是null reference.
總結:我們儘量將其他Object的reference設定等事情放在Awake處理。然後將這些reference的Object的賦值設定放在Start()中來完成。
當MonoBehavior有定義[ExecuteInEditMode]時
當我們為MonoBehavior定義了[ExecuteInEditMode]後,我們還需要關心Awake和Start在編輯器中的執行狀況。
當該MonoBehavior在編輯器中被賦於給GameObject的時候,Awake, Start 將被執行。
當Play按鈕被按下游戲開始以後,Awake, Start 將被執行。
當Play按鈕停止後,Awake, Start將再次被執行。
當在編輯器中開啟包含有該MonoBehavior的場景的時候,Awake, Start將被執行。
值得注意的是,不要用這種方式來設定一些臨時變數的儲存(private, protected)。因為一旦我們觸發Unity3D的程式碼編譯,這些變數所儲存的內容將被清為預設值。
下面再來看看Unity聖典中的解釋。
Awake()
當一個指令碼例項被載入時Awake被呼叫。
Awake用於在遊戲開始之前初始化變數或遊戲狀態。在指令碼整個生命週期內它僅被呼叫一次.Awake在所有物件被初始化之後呼叫,所以你可以安全的與其他物件對話或用諸如
GameObject.FindWithTag 這樣的函式搜尋它們。每個遊戲物體上的Awke以隨機的順序被呼叫。因此,你應該用Awake來設定指令碼間的引用,並用Start來傳遞資訊。Awake總是在Start之前被調
用。它不能用來執行協同程式。
Start()
Start僅在Update函式第一次被呼叫前呼叫。Start在behaviour的生命週期中只被呼叫一次。它和Awake的不同是Start只在指令碼例項被啟用時呼叫。
你可以按需調整延遲初始化程式碼。Awake總是在Start之前執行。這允許你協調初始化順序。
相關文章
- mysql匯入匯出指令碼的區別對比MySql指令碼
- jQuery中empty與html("")的區別對比jQueryHTML
- 對比git rm和rm的使用區別Git
- uboot中start.s原始碼指令boot原始碼
- SOAP和RESTful框架的簡介、對比和區別REST框架
- 對於java中的"\"和"/" 區別Java
- rac中 crsctl start/stop crs and crsctl start/stop cluster 區別
- 全面對比 Redis 和 Memcached 的 6 點區別Redis
- Linux 中 awk指令 sub和substr的區別Linux
- 【HBase】start master 與 start master --backup 的區別AST
- 三星 C7和榮耀8區別對比評測分析
- Linux shell指令碼中內聯輸入 <<- EOF和 <<EOF的區別Linux指令碼
- Spark與MapReduce的對比(區別)Spark
- linux 指令碼 for 與while實際中的區別Linux指令碼While
- 區塊鏈中的共識機制分析與對比區塊鏈
- jsp中include指令和include動作的區別JS
- MySQL中REPLACE INTO和INSERT INTO的區別分析MySql
- 小米Max和紅米Pro區別對比評測
- 紅米Pro和小米edge區別對比評測
- 樂2和紅米Pro區別對比評測
- 紅米pro和小米note區別對比評測
- 榮耀8和紅米4區別對比評測
- 小米5和小米note區別對比評測
- VUE的兩種跳轉push和replace對比區別Vue
- epic和steam的區別介紹及優劣對比
- OLED和LED區別對比 OLED和LED哪個好?
- 九個角度分析對比 Android、iOS開發區別AndroidiOS
- crsctl start/stop crs and crsctl start/stop cluster 區別
- 努比亞 Z11和小米Max區別對比評測
- 榮耀8和努比亞 Z11區別對比評測
- JVM原始碼分析之MetaspaceSize和MaxMetaspaceSize的區別JVM原始碼
- 小米盒子3和增強版的區別?詳細對比
- 小米 MAX和小米Note 2區別對比評測
- OPPO A59和小米5區別對比評測
- OPPO A59和小米Max區別對比評測
- 紅米Pro和小米Note 2區別對比評測
- oppo a37和紅米Pro區別對比評測
- oppo a59和紅米Pro區別對比評測