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

如何在Unity自定义Inspector中序列化自定义类?

Unity自定义Inspector实现自定义类序列化效果解决方案

核心问题说明

你之前的错误在于:

  • 不能在Editor类的方法内使用[SerializeField],这是语法错误,且局部变量无法参与Unity序列化系统。
  • EditorGUILayout.ObjectField仅用于绘制Unity对象引用(如GameObject、ScriptableObject),无法处理自定义序列化类。

要实现和MonoBehaviour中一致的自定义类序列化显示,必须借助Unity的SerializedObject和SerializedProperty系统,复用Unity默认的字段绘制逻辑。


步骤1:修正目标脚本(CardObject)结构

先确保目标类的序列化结构正确,建议用一个嵌套的可序列化类关联枚举和对应效果,方便统一管理:

using UnityEngine;
using System.Collections.Generic;

// 你的枚举类型
public enum CardEffectType
{
    None,
    DamageEffect,
    // 其他枚举值
}

// 自定义效果基类(如果是多态场景,子类继承此类)
[System.Serializable]
public class CardEffect
{
    public int damage; // 示例字段,对应你需求中的myInt
    // 其他公共字段
}

// 关联枚举和效果的可序列化条目类
[System.Serializable]
public class CardEffectEntry
{
    public CardEffectType effectType;
    [SerializeReference] // 多态场景用这个,单一类型用[SerializeField]即可
    public CardEffect effect;
}

public class CardObject : MonoBehaviour
{
    public List<CardEffectEntry> effectEntries = new List<CardEffectEntry>();
}

步骤2:自定义Editor实现动态显示

在自定义Editor中,通过SerializedProperty操作目标对象的序列化数据,根据枚举值动态绘制对应的效果类,且复用Unity默认的显示样式:

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(CardObject))]
public class CardObjectEditor : Editor
{
    private SerializedProperty _effectEntriesProp;

    private void OnEnable()
    {
        // 获取目标对象的序列化列表属性
        _effectEntriesProp = serializedObject.FindProperty("effectEntries");
    }

    public override void OnInspectorGUI()
    {
        // 更新序列化对象,同步最新数据
        serializedObject.Update();

        // 绘制整个列表(true表示自动展开折叠面板)
        EditorGUILayout.PropertyField(_effectEntriesProp, true);

        // 若需更精细的自定义绘制,可遍历列表元素
        for (int i = 0; i < _effectEntriesProp.arraySize; i++)
        {
            var entryProp = _effectEntriesProp.GetArrayElementAtIndex(i);
            var effectTypeProp = entryProp.FindPropertyRelative("effectType");
            var effectProp = entryProp.FindPropertyRelative("effect");

            // 绘制枚举选择框
            EditorGUILayout.PropertyField(effectTypeProp);

            // 判断枚举值,仅当为DamageEffect时显示效果类
            if ((CardEffectType)effectTypeProp.enumValueIndex == CardEffectType.DamageEffect)
            {
                // 用PropertyField绘制,自动复用Unity默认的自定义类序列化样式
                EditorGUILayout.PropertyField(effectProp, true);
            }

            EditorGUILayout.Space();
        }

        // 将修改应用回目标对象
        serializedObject.ApplyModifiedProperties();
    }
}

关键注意点

  • 如果你的CardEffect有多个子类(如DamageEffect : CardEffect),必须用[SerializeReference]替代[SerializeField],Unity才能正确序列化多态实例。
  • EditorGUILayout.PropertyField的第二个参数设为true,会自动生成和MonoBehaviour中一致的折叠面板,无需手动绘制每个字段。
  • 所有对目标对象的修改必须通过SerializedObject和SerializedProperty操作,才能保证数据正确序列化和撤销/重做功能正常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 11:05:22