请阅读整个问题,并在发布答案之前运行示例。
概述
在静态编辑器脚本中加载嵌套资产时,我在 Unity 5.6.1 中遇到了一些不一致的行为(因此在标有 的类的静态构造函数中[InitializeOnLoad]
)。
我正在加载一个ScriptableObject
带有 的资产Resources.Load
,并且 ScriptableObject 具有对另一个资产资源的公共引用,让我们假设一个 GameObject Prefab。从这一点开始,我将 ScriptableObject 称为“包装器”,因为在这个简化的示例中,这是它的唯一用途。
虽然Resources.Load
正确返回 Wrapper,但嵌套的 Prefab 引用通常在第一次运行期间尚未加载,但在第二次运行后加载:
据我了解,这是一个执行顺序问题,其中在静态构造期间尚未加载相关的预制资源,并且在随后的运行中它仍然被缓存。
我假设在加载具有对另一个资产的序列化引用的资产时,默认情况下会自动加载嵌套资产,无论这是否是在静态初始化期间。然而,这里似乎并非如此。
证明 Wrapper 资产确实在其序列化数据中正确引用了 Prefab(资产序列化设置为 Force Text):
我也尝试过使用AssetDAtabase.LoadAssetAtPath
(至少在编辑器中),但并没有什么不同。
示例项目
您可以在此处下载 UnityPackage,其中包含以下内容:
或者复制如下:
脚本:
ExampleWrapper.cs:
using UnityEngine; public class ExampleWrapper : ScriptableObject { public GameObject Value; }
静态加载器.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 } }
在 Hierarchy 中创建一个空的“ExampleObject”游戏对象,然后将其保存为 Prefab
Assets/Resources/ExampleObject.prefab
创建 ExampleWrapper 的资产实例并在
Assets/Resources/Wrapper.asset
请注意,因为有时 unity 确实会正确缓存资产,
基本原理
这里的示例是故意简化的,但它基于ScriptableObjects
用于存储/共享自定义系统配置数据的真实项目。
请不要回复以下内容:
- “Just Use
Object.Instantiate
” - 不改变结果,Resources.Load
在某些情况下修改返回的原始对象是可取的。 - “跳过包装器并直接引用预制件/手动加载它” - 虽然这绕过了加载问题,但它也错过了问题的重点。添加抽象级别可以使系统之间的资源共享更易于维护。此外,此问题不仅限于预制件(此处仅用于简单示例)。更现实的示例将包含多个嵌套对象,例如 Sprites、Materials、其他 ScriptableObjects 等。
- “在静态构建期间不要加载” - Unity 支持静态系统(为什么还要提供
[InitializeOnLoad]
?),并且使用基于 ScriptableObjects 的资产来存储此类系统的配置信息是一个非常真实的用例。在完全重新构建系统之前,我想看看其他潜在的替代方案。
我在找什么:
- 当我在诸如此类的静态上下文中加载它时,我是否可以强制 Unity 预加载在包装器中序列化的资产,而不必通过其路径手动加载其内容?
- 换句话说,我不想只是 run
Resources.Load<GameObject>("ExampleObject")
,因为这首先会否定封装它的全部意义。我可以修改ExampleWrapper
类,但是任何潜在的解决方案都需要足够自动化,以便将预制件添加到检查器中的字段的工作流程将是所有需要的。
编辑:还应该注意的是,奇怪的是,当我关闭项目并再次打开它时,我看到以下内容:
- 在启动过程中,静态构造函数被调用一次,包装器被加载,嵌套的预制件实际上被正确加载。
- 然后(仍然在初始启动中,因为它发生在我可以输入任何动作之前)它再次静态构造,这次加载 Wrapper 时,没有加载嵌套的预制件。
这个,我真的不明白。