關於DontDestroyOnLoad的一點筆記
由於Unity中實例化GameObject
的代價是比較高的,所以項目利用DontDestroyOnLoad
做了一個可重復回收再利用的東西,關鍵代碼是:Instantiate
預設之后,調用DontDestoryOnLoad
來包裝一次,並且用一個列表List來保存這個物體的引用,當物體不再使用時,使用transform.SetParent(null,false)
來隱藏掉.最后在這個界面被OnDestroy時,手動Destroy掉List里的每一個物體.
拋開設計思路不談,問題是當游戲切換場景時,會拋出錯誤,雖然不影響實際游戲,但畢竟是個Error:MissingReferenceException: The object of type 'AppComment' has been destroyed but you are still trying to access it. Your script should either check if it is null or you should not destroy the object.
這顯然是物體被Destroy了兩次,意味着在場景被Unload
的時候物體已經被摧毀了,然后再次在腳本里Destroy
的時候就報錯了.怎么回事呢?很久之前在看這個問題了,今天又在網上查了半天,原來是當GameObject
被使用后,會破壞掉DontDestroyOnLoad
的標記.在Editor里面我們可以在DontDestroyOnLoad
場景追蹤到所有被標記為DontDestroyOnLoad
的GameObject
,但在物體被使用時,肯定會將它的Parent
設定為當前活躍場景的一個對象,所以DontDestroyOnLoad
的標簽就被打破了.
具體的可以可以看Unity論壇的問題:撤銷DontDestroyOnLoad.
另外關於一點DontDestroyOnLoad場景的說明:DontDestroyOnLoad並不是一個場景,通過SceneManager獲取到的會是一個Invalid Scene,你也無法通過GetRootGameObjects
來獲取該場景的所有跟物體.這個場景僅僅是為了方便在Editor中檢視帶有DontDestroyOnLoad
標記的物體而存在的,而在Runtime中是不存在的.Unity手冊中可以找到關於這些的描述:Play mode部分.
如果需要通過找場景的方式來獲取所有帶有DontDestroyOnLoad
標記的物體,可以通過一個小科技,具體查看鏈接的回答(沒試驗過):
獲取所有DontDestroyOnLoad
物體,並且按照外國友人的說法,這個黑科技也只在Editor中有效.