如何在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
相关产品推荐
相关产品推荐

