[Unity3D]指令碼中Start()和Awake()的區別

來源:互聯網
上載者:User

學習Unity指令碼推薦:Unity3D官網索引


Unity3D初學者經常把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之前執行。這允許你協調初始化順序。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.