为什么未加载 ScriptableObject 资产中的嵌套资源引用?

Why are nested resources references in a ScriptableObject asset not loaded?

请在发布答案之前阅读整个问题和运行示例。


概述

我 运行 在静态编辑器脚本中加载 嵌套 资产时,我 运行 在 Unity 5.6.1 中出现一些不一致的行为(因此在 class 标记为 [InitializeOnLoad]).

我正在加载一个 ScriptableObject Asset with Resources.Load,并且 ScriptableObject 有一个对另一个资产资源的 public 引用,让我们假设一个 GameObject Prefab。从这一点开始,我将 ScriptableObject 称为 'Wrapper',因为在这个简化的示例中,这是它服务的唯一目的。

虽然 Resources.Load 正确地 returns 包装器,但嵌套的 Prefab 引用通常在第一个 运行 期间尚未加载,但在第二个 运行 之后加载:

据我了解,这是一个执行顺序问题,其中有问题的预制资源在静态构建期间尚未加载,并且在随后的 运行 中它仍然被缓存。

我假设当加载一个资产并引用另一个资产时,嵌套资产将默认自动加载,无论这是否在静态初始化期间。然而,这里似乎并非如此。

证明 Wrapper 资产确实在其序列化数据中正确引用了 Prefab(使用 Asset Serialization set to Force Text):

我也尝试过使用 AssetDAtabase.LoadAssetAtPath(至少在编辑器中是这样),但没有什么不同。


示例项目

您可以下载一个UnityPackage here,其中包含以下内容:

或重现如下:


理由

此处的示例有意简化,但它基于使用 ScriptableObjects 用于自定义系统的 storing/sharing 配置数据的真实项目。

不要回复以下内容:

正在寻找什么:


编辑: 还应该注意的是,奇怪的是,当我关闭项目并再次打开它时,我看到以下内容:

这个,我真的不懂

你的问题存在误解。

引用传递给Loaderclass,场景初始化完成后可以通过loggingWrapper.Value查看。

很可能,问题出在(如您所指出的)execution/serialization 顺序中,显然是这样发生的:

  • 调用了Loader构造函数,正确传递了Wrapper引用。
  • Debug.Log(Wrapper.Value) returns null 因为脚本对象的字段还没有被序列化
  • Wrapper 的字段已序列化,现在记录 Wrapper.Value 正确显示 ExampleObject.

因此,除非您计划 "special" 在初始化期间对 Wrapper 字段进行处理,否则您的代码确实没有问题:我尝试 运行 Debug.Log(Loader.Wrapper.Value)ExampleWrapperOnEnable 期间,我得到了正确的值。

关于您的编辑,显然它发生了 "by Design",正如本期中明确指出的那样:https://issuetracker.unity3d.com/issues/unityeditor-dot-initializeonload-calls-the-constructor-twice-when-the-editor-opens