請閱讀整個問題,並在發佈答案前運行該示例。爲什麼在未加載的ScriptableObject資源中引用嵌套資源?
概述
我在Unity 5.6.1靜態編輯腳本加載嵌套資產(所以在標有[InitializeOnLoad]
一類的靜態構造函數)時遇到了一些不一致的行爲。
我正在加載ScriptableObject
資產Resources.Load
,並且ScriptableObject具有對另一資產資源的公共引用,我們假設一個GameObject Prefab。從這一點來說,我將把ScriptableObject稱爲'包裝器',因爲在這個簡化的例子中,它是它唯一的目的。
雖然Resources.Load
正確返回包裝,嵌套預製參考的往往不是第一次運行時沒有加載,但第二次運行後載入:
我的理解是,這是一個數量級在靜態構造期間尚未加載有問題的Prefab資源的執行問題,並且在隨後的運行中它仍然被緩存。
我認爲在資產中加載帶有對另一資產的序列化引用的資產時,嵌套資產會默認自動加載,無論這是否在靜態初始化過程中。但是,這似乎並不是這種情況。
證明,包裝資產確實正確地引用預製在它的序列化數據(與Asset Serialization set to Force Text):
我也曾嘗試使用AssetDAtabase.LoadAssetAtPath
(至少同時在編輯器),它並沒有作出一個區別。
示例項目
你可以下載一個UnityPackage here,它包含以下內容:
或者如下重現:
腳本:
個ExampleWrapper.cs:
using UnityEngine; public class ExampleWrapper : ScriptableObject { public GameObject Value; }
StaticLoader。CS:
using UnityEngine; #if UNITY_EDITOR using UnityEditor; [InitializeOnLoad] #endif public class Loader { static Loader() { var Wrapper = Resources.Load<ExampleWrapper>("Wrapper"); Debug.Log(Wrapper); // Prints the Wrapper ScriptableObject Debug.Log(Wrapper.Value); // Prints the Wrapped GameObject } }
創建層次空 「ExampleObject」 遊戲物體,然後將其保存爲預製在
Assets/Resources/ExampleObject.prefab
創建ExampleWrapper,並在
資產實例Assets/Resources/Wrapper.asset
- 由於Unity 5不提供用於產生ScriptableObjects的UI,因此您可以創建您的own menu item或使用an automated solution。這個問題假定你對ScriptableObjects有足夠的熟悉,並擁有你自己的首選方法。
注意,因爲有時候團結不正確緩存資產,
理由
示例這裏是故意簡化的,但它基於使用ScriptableObjects
的實際項目來存儲/共享定製系統的配置數據。
請不要回覆下列要求:
- 「只是使用
Object.Instantiate
」 - 不改變結果,並修改由Resources.Load
返回的原始對象在某些情況下是可取的。 - 「跳過包裝,直接參考預製/手動加載」 - 雖然這繞過了加載問題,但它也忽略了問題的重點。增加抽象級別可以使系統之間的共享資源更易於維護。此外,這個問題不僅限於Prefabs(這裏僅用於簡單示例)。更現實的例子將包含多個嵌套的對象,如精靈,材料,其他ScriptableObjects等
- 「靜施工期間不加載」 - 靜態系統通過統一的支持(?爲什麼別人提供
[InitializeOnLoad]
),並使用基於ScriptableObjects存儲這些系統的配置信息的資產是非常實際的用例。在完全重新設計系統之前,我想看看其他潛在的選擇。
我是尋找:
- 是否有可能對我來說,強制統一預加載在包裝序列化的資產,當我在靜態情況下加載它像這樣,而無需通過路徑手動加載其內容?
- 換句話說,我不想僅僅運行
Resources.Load<GameObject>("ExampleObject")
,因爲這會否定將它封裝在第一位的整個觀點。我很喜歡修改ExampleWrapper
類,但任何可能的解決方案都需要足夠自動化,以便將預製件添加到檢查器的現場的工作流程將全部需要。
編輯:還應當指出的是古怪的是,當我關閉項目,打開它,我再次看到以下內容:
- 在啓動過程中,靜態構造函數被調用一次,Wrapper被加載,並且嵌套預製爲實際加載正確。
- 然後(仍然在初始啓動過程中,因爲它發生在我可以輸入任何動作之前),它再次靜態構造,並且這次當包裝被加載時,嵌套的預製件不是加載。
這個,我真的不明白。
首先,你說'Resources.Load'不工作的第一次,那麼你說你不;噸甚至想要使用'Resources.Load' ...你想聽到什麼作爲答案?你想用什麼? – Programmer
我想在包裝器上使用'Resource.Load',而不是在每個包裝的資源上手動調用'Resource.Load',因爲這會破壞將它們包裝在一個包裝器中的要點。請參閱Galandil的回答,尋找我正在尋找的有用信息。 – Johannes