前幾天有場直播跟大家分享我對 Unity MonoBehaviour 的一些心得,花了一個小時左右跟觀眾討論一些在 Unity 開發時容易遇到的問題,以及一些零碎的小細節。
之後的一個多小時,則是閱讀 Unity 官方文件以及進行測試,目的是希望了解 Awake、Start、Update、OnDestroy、OnEnable 等 MonoBehaviour 事件(Message enent) 的執行細節。
直播紀錄與實驗紀錄如下:
2017/2/21 直播紀錄 (Unity 開發 | Monobehaviour 機制說明與測試)
直播及後續研究得到的一些結論
關於場景初始化
- 對於一個物件,初始化動作的執行順序為 Awake > OnEnable > Start。
- 進入場景後,所有物件的 Awake、OnEnable 都會在所有物件的 Start 之前執行;換句話說, Awake、OnEnable 是初始化的階段一,Start 是初始化的階段二。
- 對開發腳本的建議是,Awake 不要使用到橫跨腳本或物件的功能,如 GameObject.Find 及 gameObject.GetComponent 後制執行方法或存取變數。
- 數個物件之間並沒有保證 Awake 一定會在 OnEnable 之前。
- 對於剛進入場景時便存在的物件而言,物件之間 Start 必定在 Update 之前,但後來被建立的物件則不再此限。
- 建議不要依賴這項原則,可能會造成物件或腳本的不穩定。
關於 Instantiate
- 在 GameObject.Instantiate 語法執行完的同時,可以理解為 Awake、OnEnable 都被執行過了,但 Start 並還沒執行。
- Start 跟 Update 會在同一個 Frame 執行,但依據 GameObject.Instantiate 語法執行的時間點,可能會需要等到下一個 Frame。
關於 Destroy
- 執行了 GameObject.Destroy 語法的當下,並不會執行 OnDestroy,所以有即時動作之必要時,不建議使用 OnDestroy。
- OnDestroy 執行的時間點,是在該物件最後一次執行 Update 之後。
更多關於 Awake、Start、FixedUpdate
- Awake 基本上一定會被執行到。
- 如果物件還沒執行 Start 就遭到 Destory,則 Start 不會執行。
- FixedUpdate 是物理邏輯所使用,雖然是固定的時間運作,但對於 Frame 更新來說,它是不同步的,使用 FixedUpdate 來處理畫面相關可能會造成畫面的不連續的延遲感。
關於切換場景
- 因為 MonoBehaviour 的 Coroutine 多在 Update 階段執行,所以 Coroutine 中的動作不會早於新場景的 Awake、OnEnable、Start
- Coroutine 是依附於 MonoBehaviour 及物件上,所以切換場景後,不論 Coroutine 中的工作是否完成,都會被銷毀。
- 所以建議要在 Coroutine 中執行場景切換,或跨場景相關的工作,要採用 DontDestroy 物件或 Singleton pattern。
後話
這是一場臨時且雜亂的直播 (而且前半音效設備有狀況),不過在開頭的一個小時因為有觀眾互動,我就嘰嘰喳喳地說了很多零碎的感想,希望有帶給觀眾有用的資訊。
關於場景切換時,該如何插入一些腳本工作在初始化階段之中或之前,還沒有確定結論。如果有了新的結果會在分享給大家。
2017/02/28 update:
新文章補完了關於場景切換中,安插腳本的流程 (Flow) 測試
廣告