Unity腳本生命周期與執行順序
目錄
- 腳本生命周期
- MonoBehavior生命周期圖
- 腳本執行順序
- 自定義執行順序
@(文章目錄)
在Unity中,腳本可以理解為附加在遊戲對象上的用於定義遊戲對象行為的指令代碼。必須綁定在遊戲對象上才能開始它的生命周期。遊戲對象可以理解為能容納各種組件的容器,遊戲對象的所有組件一起決定了這個對象的行為和遊戲中的表現。
腳本生命周期
Unity腳本中的常見必然事件如下表所示
名稱 | 觸發時機 | 用途 |
---|---|---|
Awake | 腳本實例被創建時調用 | 用於遊戲對象的初始化,註意Awake的執行早於所有腳本的Start函數 |
OnEnable | 當對象變為可用或激活狀態時被調用 | 用途 |
Start | Update函數第一次運行之前調用 | 用於遊戲對象的初始化 |
Update | 每幀調用一次 | 用於更新遊戲場景和狀態 |
FixedUpdate | 每個固定物理時間間隔調用一次 | 用於物理狀態的更新 |
LateUpdate | 每幀調用一次(在update之後調用) | 用於更新遊戲場景和狀態,和相機有關的更新一般放在這裏 |
OnGUI | 渲染和處理OnGUI事件 | 用途 |
OnDisable | 當前對象不可用或非激活狀態時被調用 | 用途 |
OnDestroy | 當前對象被銷毀時調用 | 用途 |
下面將以代碼來看看這些必然事件的調用時機
新建一個C#腳本,並添加以下代碼,然後將其掛到任意的遊戲對象上
using System.Collections; using System.Collections.Generic; using UnityEngine; public class TestTest : MonoBehaviour { private void Awake() { Debug.Log("Awake"); } private void OnEnable() { Debug.Log("OnEnable"); } // Start is called before the first frame update void Start() { Debug.Log("Start"); } // Update is called once per frame void Update() { Debug.Log("Update"); } private void FixedUpdate() { Debug.Log("FixedUpdate"); } private void LateUpdate() { Debug.Log("LateUpdate"); } private void OnGUI() { Debug.Log("OnGUI"); } private void OnDisable() { Debug.Log("OnDisable"); } private void OnDestroy() { Debug.Log("OnDestroy"); } }
打印結果如下圖示:
可以發現,Awake, Start函數都是在遊戲對象被創建時調用一次。
當遊戲過程中調整腳本的可見狀態時,會分別調用OnEnable, OnDisable函數,而Awake和Start將不會再調用,也就是說一旦腳本被掛載上以後,Awake和Start有且僅會被執行一次。
而Update, FixedUpdate, LateUpdate, OnGUI函數是會在遊戲過程中被多次調用的(日誌窗口右側的數字表示該條日誌信息打印的次數)。
最後在遊戲對象被銷毀時,會依次調用OnDisable, OnDestory函數。
MonoBehavior生命周期圖
下面再放上一張外國友人所畫的生命周期圖
腳本執行順序
在遊戲開發中,不可避免的會使用許多腳本,那麽如何確定不同腳本之間調用的先後順序呢
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test1 : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
Debug.Log("start 1");
}
private void Awake()
{
Debug.Log("awake 1");
}
// Update is called once per frame
void Update()
{
Debug.Log("update 1");
}
}
將上面的代碼依次添加到Test1, Test2和Test3腳本中(適當修改打印的日誌),並掛載到不同的遊戲對象上。
掛載的順序為先掛載Test3,再掛載Test2,最後掛載Test1
打印結果如下圖所示
打印結果是先打印Test1的,再打印Test2,最後打印Test3。
其實腳本的執行順序與掛載到遊戲對象上的先後順序有關。最先被掛載的最後執行,最後被掛載的最先執行(如果讀者有疑惑,可以不斷調整腳本的掛載順序,看日誌打印與上述結論是否相符)。
需要註意的是,無論多個腳本的執行順序如何,但所有腳本的Awake函數一定會比所有的Start函數先執行完,所有的Start函數一定也會比所有的Update函數先執行完,其他有順序的生命周期函數也是類似的(從上圖的日誌信息中也可以看出)。
自定義執行順序
有時可能有這樣的需求,A腳本中的屬性實例化可能需要用到B腳本中的屬性,所以在A腳本屬性實例化時,必須保證B腳本已經被實例化完畢。當然我們可以通過先掛在A腳本再掛載B腳本來實現。但在實際開發中,用到的腳本中多,很難去記住各個腳本掛載的先後順序。所以Unity提供了Script Execution Order配置項,來配置多個腳本的執行順序。
在工程面板中任意點擊選中一個腳本文件,在屬性面板中會出現該腳本的詳細信息,選擇右上角的Execution Order...
,打開如下圖所示界面
點擊“+”可以添加腳本,為其設置order值,order值越小的越先執行,order值越大的越後執行
Unity腳本生命周期與執行順序