【Unity筆記】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函數,將會在這段代碼執行后觸發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]后,我們還需要關心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 這樣的函數搜索它們。每個游戲物體上的Awake以隨機的順序被調用。因此,你應該用Awake來設置腳本間的引用,並用Start來傳遞信息。Awake總是在Start之前被調用。它不能用來執行協同程序。

Start()
Start僅在Update函數第一次被調用前調用。Start在behaviour的生命周期中只被調用一次。它和Awake的不同是Start只在腳本實例被啟用時調用。 你可以按需調整延遲初始化代碼。Awake總是在Start之前執行。這允許你協調初始化順序。


總結——個人理解

Awake

  • 初始化函數,游戲開始時系統自動調用
  • 一般用來聲明變量
  • 所掛載的物體被激活時,才能被調用
  • 當被添加到物體身上時,就立即被調用
  • 無論該腳本組件是否激活,都會被調用
  • 所有的Awake函數被調用的先后順序不一定(暫且存疑)
  • 在所有的Start函數之前被調用

Start

  • 初始化函數,在所有Awake函數運行完之后,Update函數首次運行之前,被調用
  • 一般用來給變量賦值
  • 所掛載的物體被激活時,才能被調用
  • 腳本在代碼中被實例化時才開始調用
  • 只有該腳本組件被激活時,才能被調用

注意:只要場景中有已激活的物體身上承載該腳本,無論該腳本是否被激活,Awake函數都會被調用。但是只有腳本已被激活,Start函數才能被調用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM