Unity 编辑器扩展

复制代码
[CustomEditor(typeof(XXXConfig))]
public class XXXConfigEditor : UnityEditor.Editor

这是一个 属性标签(Attribute),告诉 Unity:

"当用户在 Inspector 中选中一个 XXXConfig 类型的 ScriptableObject 资产时,不要用默认的 Inspector,而是用我写的 XXXConfigEditor 来渲染面板。"

复制代码
用户在 Hierarchy/Project 中选中 XXXConfig 资产
    ↓
Unity 检测到 [CustomEditor(typeof(XXXConfig))]
    ↓
实例化 XXXConfigEditor
    ↓
调用 OnInspectorGUI() 方法(你必须重写这个方法)
    ↓
你在 OnInspectorGUI() 里用 GUILayout/EditorGUILayout 绘制自定义控件
    ↓
用户点击按钮、修改字段 → 通过 serializedObject.ApplyModifiedProperties() 保存修改

serializedObject 是继承自 UnityEditor.Editor 基类的内置属性

复制代码
public class XXXConfigEditor : UnityEditor.Editor  // 继承了 Editor
{
    // serializedObject 来自父类 UnityEditor.Editor
    // 你不需要声明,直接用就行
}

serializedObjectSerializedObject 类型 ,它是你正在编辑的目标资产(即 TutorialConfig 实例)的序列化包装器

核心作用

作用 说明
读取字段 通过 serializedObject.FindProperty("fieldName") 访问资产里的字段
修改字段 通过 property.intValue = xxx 修改值
保存修改 调用 serializedObject.ApplyModifiedProperties() 把修改写入磁盘
撤销支持 配合 Undo.RecordObject() 实现 Ctrl+Z 撤销
多对象编辑 同时选中多个资产时,自动处理共有的可编辑字段
复制代码
public override void OnInspectorGUI()
{
    // 1. 更新序列化对象(从磁盘读取最新状态)
    serializedObject.Update();

    // 2. 获取字段
    SerializedProperty xxList = serializedObject.FindProperty("lists");

    // 3. 绘制字段(Unity 自动处理 UI)
    EditorGUILayout.PropertyField(xxList);

    // 4. 应用修改(保存回资产文件)
    serializedObject.ApplyModifiedProperties();
}

ReorderableList 是 Unity 编辑器内置的可拖拽排序列表控件,专门用于在 Inspector 中展示和操作数组/列表。

复制代码
using UnityEditorInternal;  // 命名空间

ReorderableList list = new ReorderableList(serializedObject, property);

它提供了一个可视化的列表 UI,支持:

功能 说明
拖拽排序 鼠标拖拽元素上下移动
添加/删除 右侧有 + - 按钮
折叠/展开 点击左侧箭头展开子字段
多选 支持框选多个元素批量操作
自定义绘制 可以重写回调方法自定义每个元素的显示
复制代码
var dropdown = new StageTypeDropdown(_dropdownState, onSelected);
dropdown.Show(buttonRect); 


当执行 dropdown.Show(buttonRect) 时,Unity 内部的 AdvancedDropdown 会:
弹出下拉框窗口
立即调用 BuildRoot() 构建下拉框的内容树
渲染树节点显示给用户


用户点击 ReorderableList 的 + 按钮
    ↓
onAddDropdownCallback 触发
    ↓
StageTypeSelector.Show(buttonRect, OnStageTypeSelected)
    ↓
new StageTypeDropdown(...)  // 创建实例
    ↓
dropdown.Show(buttonRect)   // 显示下拉框
    ↓
[Unity 内部] AdvancedDropdown.Show()
    ↓
[Unity 内部] 调用 BuildRoot()  ← 你的重写方法在这里被调用
    ↓
返回 AdvancedDropdownItem 根节点
    ↓
渲染下拉框内容

[SerializeReference]

复制代码
    [Serializable]
    public abstract class BaseType
    {
        [SerializeField] private string _typeName= "xxx";
    }

// ❌ 默认序列化:只保存基类字段,丢失子类信息
public List<BaseType> BaseTypes;  

// ✅ 使用 SerializeReference:保存实际类型 + 子类字段
[SerializeReference]
public List<BaseType> BaseTypes; 
默认序列化 [SerializeReference]
序列化时 只保存基类 Stage 的字段 保存实际类型 + 所有字段
反序列化后 变成 Stage(基类) 还原为 FocusSampleStage(子类)
子类字段 丢失 完整保留
null 值 不允许(总是创建实例) 允许 null
多态引用 不支持 支持
复制代码
// ✅ 接口
[SerializeReference] public ITrigger Trigger;

// ✅ 抽象类
[SerializeReference] public Stage CurrentStage;

// ✅ 数组/列表
[SerializeReference] public List<Stage> Stages;

// ❌ 不能用在值类型(struct、int、Color 等)
[SerializeReference] public int Value;  // 编译报错

// ❌ 不能用在继承自 MonoBehaviour/ScriptableObject 的类
[SerializeReference] public MyMonoBehaviour Ref;  // 运行时报错

// ❌ 不能用在 GameObject/Transform 等 Unity 原生对象
[SerializeReference] public GameObject Go;  // 不生效

子类必须标注 [Serializable]
[Serializable]  // ← 必须!
public class TestTypes : BaseType
{
    [SerializeField] private float _animationDuration;
}


字段本身不需要再加 [SerializeField]

// [SerializeReference] 本身就表示"参与序列化",不需要 [SerializeField]
[SerializeReference] public List<BaseType> baseTypes;

// 但子类内部的字段仍然需要 [SerializeField]
[Serializable]
public class TestTypes: BaseType
{
    [SerializeField] private float _duration;  // ← 需要
}
相关推荐
程序员正茂11 小时前
Unity3d使用MQTT异步连接服务端
mqtt·unity·异步
mxwin13 小时前
在unity shader中,通过pass产生阴影,通过主pass的光照 接收阴影!那么问题来了,是先产生阴影吗?还是先接收阴影,执行顺序是啥呢
数码相机·unity·游戏引擎·shader
小贺儿开发14 小时前
《唐朝诡事录之长安》——盛世马球
人工智能·unity·ai·shader·绘画·影视·互动
Eric.Lee202121 小时前
vscode格式化代码
ide·vscode·编辑器·c++格式化
蒙双眼看世界1 天前
Unity结合ECharts图表及网页插件EmbeddedBrowser的应用开发
unity·游戏引擎·echarts
【 STM32开发 】1 天前
VSCode 安装图解
ide·vscode·编辑器
IOT.FIVE.NO.11 天前
Codex、Claude Code、Cherry Studio 实测对比:CLI、桌面端怎么选?
ide·人工智能·编辑器·ai编程·ai写作·visual studio·vibecoding
郝学胜-神的一滴1 天前
中级OpenGL教程 004:为几何体注入法线灵魂
c++·unity·游戏引擎·godot·图形渲染·opengl·unreal
笑望灬星辰2 天前
VS Code 编辑器 Git 工具 - 分支操作【保姆级教程】
git·vscode·编辑器