You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity Editor嵌套ScriptableObject内部字段无法序列化问题咨询

解决方案说明

Unity 默认序列化规则中,嵌套的ScriptableObject引用仅会序列化资源ID,Inspector默认仅展示引用选择器,不会展开内部字段;且直接修改引用SO的字段会改动原始资源,无法实现同一份SO模板在不同上下文下的差异化配置。

方案1:中间包装类(最推荐,符合复用需求)

直接定义可序列化的包装结构,将公共模板引用和差异化字段分开存储,差异化字段序列化在上层ScriptableExpressionCreator中,不会修改原始SO资源,无需自定义编辑器即可原生支持Inspector编辑。
代码示例:

[System.Serializable]
public class ExpressionBuilderEntry
{
    // 公共模板,所有引用位置共用MultipleExpressionBuilder等配置
    public ScriptableExpressionBuilder builderTemplate;
    // 当前上下文独有的delay值,仅保存在当前Creator资源中
    public float overrideDelay;

    // 可选:封装取值逻辑,支持默认用模板delay的 fallback 逻辑
    public float GetFinalDelay()
    {
        // 例:overrideDelay设为-1时用模板默认值,否则用自定义值
        return overrideDelay < 0 ? builderTemplate.delay : overrideDelay;
    }
}

修改ScriptableExpressionCreator的列表定义:

public class ScriptableExpressionCreator : ScriptableObject 
{
    public List<ExpressionBuilderEntry> builderEntries;
}

业务逻辑中取值时,直接调用entry.GetFinalDelay()即可,原始SO的MultipleExpressionBuilder配置可通过entry.builderTemplate.multipleExpressionBuilder正常读取。

方案2:自定义Inspector内嵌编辑(适合复杂编辑需求)

如果需要在Creator的Inspector中直接展示ScriptableExpressionBuilder的完整字段,同时支持覆写存储,可以为ScriptableExpressionCreator实现自定义Editor,动态创建每个SO的内嵌Inspector,同时自己维护覆写字段的存储逻辑,避免修改原始SO资源。
核心编辑器代码示例(放在Editor目录下):

[CustomEditor(typeof(ScriptableExpressionCreator))]
public class ExpressionCreatorEditor : Editor
{
    private SerializedProperty _entriesProp;
    private readonly Dictionary<ScriptableExpressionBuilder, Editor> _cachedEditors = new();

    private void OnEnable()
    {
        _entriesProp = serializedObject.FindProperty("builderEntries");
    }

    public override void OnInspectorGUI()
    {
        serializedObject.Update();
        for (int i = 0; i < _entriesProp.arraySize; i++)
        {
            var entryProp = _entriesProp.GetArrayElementAtIndex(i);
            var templateProp = entryProp.FindPropertyRelative("builderTemplate");
            var delayProp = entryProp.FindPropertyRelative("overrideDelay");
            
            EditorGUILayout.PropertyField(templateProp);
            if (templateProp.objectReferenceValue is ScriptableExpressionBuilder builder)
            {
                EditorGUI.indentLevel++;
                // 显示覆写delay字段
                EditorGUILayout.PropertyField(delayProp);
                // 可选:展示模板的只读公共配置
                if (!_cachedEditors.TryGetValue(builder, out var editor))
                {
                    Editor.CreateCachedEditor(builder, null, ref editor);
                    _cachedEditors[builder] = editor;
                }
                using (new EditorGUI.DisabledScope(true))
                {
                    editor.OnInspectorGUI();
                }
                EditorGUI.indentLevel--;
            }
            EditorGUILayout.Space();
        }
        serializedObject.ApplyModifiedProperties();
    }
}

不推荐方案:取消ScriptableObject继承

如果不需要公共复用ScriptableExpressionBuilder资源,可以将其改为普通可序列化类,去掉ScriptableObject继承并加[Serializable]标记,上层列表会自动展开所有字段序列化,但无法实现同一份模板多场景复用的需求。

内容的提问来源于stack exchange,提问作者rootpanthera

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 20:18:03