Unity腳本生命週期與執行順序

@(文章目錄)日誌

在Unity中,腳本能夠理解爲附加在遊戲對象上的用於定義遊戲對象行爲的指令代碼。必須綁定在遊戲對象上才能開始它的生命週期。遊戲對象能夠理解爲能容納各類組件的容器,遊戲對象的全部組件一塊兒決定了這個對象的行爲和遊戲中的表現。code

腳本生命週期

Unity腳本中的常見必然事件以下表所示對象

名稱 觸發時機 用途
Awake 腳本實例被建立時調用 用於遊戲對象的初始化,注意Awake的執行早於全部腳本的Start函數
OnEnable 當對象變爲可用或激活狀態時被調用 用途
Start Update函數第一次運行以前調用 用於遊戲對象的初始化
Update 每幀調用一次 用於更新遊戲場景和狀態
FixedUpdate 每一個固定物理時間間隔調用一次 用於物理狀態的更新
LateUpdate 每幀調用一次(在update以後調用) 用於更新遊戲場景和狀態,和相機有關的更新通常放在這裏
OnGUI 渲染和處理OnGUI事件 用途
OnDisable 當前對象不可用或非激活狀態時被調用 用途
OnDestroy 當前對象被銷燬時調用 用途

下面將以代碼來看看這些必然事件的調用時機
新建一個C#腳本,並添加如下代碼,而後將其掛到任意的遊戲對象上blog

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生命週期圖

下面再放上一張外國友人所畫的生命週期圖事件

生命週期圖

腳本執行順序

在遊戲開發中,不可避免的會使用許多腳本,那麼如何肯定不一樣腳本之間調用的前後順序呢ip

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值越大的越後執行

相關文章
相關標籤/搜索