我們都知道,Unity中,某個游戲物體上的腳本初始化順序是先Awake,再Start,那么假如現在有這樣一種情況:
有兩個模塊,它們都通過Awake或者Start來初始化,但其中一個會持有對另一個模塊的引用,更具體一點,比如腳本1是單例的,腳本2中持有對腳本1的引用,而且腳本2會在初始化的時候將引用賦值為腳本1的單例。
此時萬一腳本2的Awake和Start先執行,那初始化時由於腳本1還沒有初始化,肯定會出錯,怎么辦呢?
一種解決方案是在Edit->Project Settings->Script Execution Order下設置腳本先后次序,可以參考:
https://jingyan.baidu.com/article/0a52e3f4d47152bf62ed7297.html
但這種方案當互相依賴的腳本比較多時,會比較繁瑣。
另一種方案是把模塊初始化的內容放在一個單獨的函數里,模塊內部不再使用Awake和Start。這樣,我們就可以在一個管理腳本中分別控制每個模塊的初始化順序,不會導致沖突。這是游戲開發的一種常用思路,雖然不涉及什么難的技術,但這種思想值得參考。
我們先介紹一種常用的游戲開發架構思路:
一種常見思路是創建一個空物體,將一個管理模塊的腳本掛在此物體下,它負責啟動游戲並初始化各個模塊,根據游戲中各個部分功能的不同,不同的腳本大致可分為公共服務模塊和單個業務系統模塊,公共服務模塊會向系統中的所有模塊提供一些公共服務,比如資源加載,音頻播放,網絡服務等等。
單個業務系統模塊分為很多種,比如登錄系統業務模塊,戰斗業務模塊,副本業務模塊等等,各個單獨業務模塊負責管理本業務相關的腳本,比如某些UI窗口下是某個業務模塊的界面,每個UI窗口下都會有對應的窗口管理腳本,這些窗口管理腳本就是由對應歸屬的單個業務系統模塊腳本來操控的,反映到代碼上,就是這些業務模塊腳本會持有這些窗口管理腳本的引用。
而公共服務模塊和單個業務系統模塊,是統一由管理模塊初始化的,因此管理模塊中需要持有對這兩個模塊的引用,我們可以不使用拖拽的方式來實現,可以將這兩個模塊與管理模塊一起,放在空物體下,管理模塊初始化時用代碼獲取這兩個模塊的引用,並控制這兩個模塊的初始化順序。
下面給出實現的代碼和結果:
GameRoot是管理模塊,PublicSvc是公共服務模塊,SingleSys是單個業務系統模塊,由於業務系統模塊中需要用到公共服務模塊提供的服務,因此需要先初始化公共服務模塊,再初始化業務模塊。
再看一下它們在系統中的排布:
它們都放在空物體GameRoot下,方便GameRoot腳本取到對服務模塊和業務模塊的引用。
輸出結果如下:
完結。