Unity 6 ScriptableObject 架构
将以下提示词粘贴到你的 AI 对话框中:
请根据 https://skillhub.cn/install/skillhub.md,安装 @user_3c6cb52e/unity-scriptableobjects-sh-34g4tf。
技能介绍
问题从哪来
Unity 项目里,武器数值、关卡表、HUD 与玩家之间的信号,常被塞进场景里的 MonoBehaviour 或静态单例。结果是:策划难改数据、系统互相引用、Play 一次后编辑器里的数值「莫名其妙」被改掉。ScriptableObject 把共享数据做成项目资产(.asset),由多个组件引用同一份实例,而不是各自拷贝一份。
本技能面向 Unity 6(6000.0 LTS),说明如何用 SO 做配置、事件通道和运行时注册表,并避开最常见的误用。
核心工作流
- 定义类:继承
ScriptableObject,用[CreateAssetMenu]让策划在 Assets 菜单里创建实例。 - 建
.asset:在 Project 窗口创建命名数据;MonoBehaviour用[SerializeField]引用资产,不要复制字段值。 - 解耦:把「浮点共享变量」「事件通道」也做成 SO——HUD 读、玩家写;发送方
Raise、多方监听,彼此不直接引用。 - 运行时改动要复位:若在 Play 中修改了资产,编辑器里会持久保留;可变运行时状态应放在
[NonSerialized]并在OnEnable里重置(关闭 Domain Reload 时OnEnable可能不触发,需另找序列化或场景加载钩子)。 - 验证:Play 模式下检查资产字段,确认所有消费者同步响应。
文档还归纳三类模式:配置/数据资产、共享运行时变量、运行时 CreateInstance(非磁盘资产);事件通道与运行时集合详见 references/event-channels.md。
适用边界与坑
- 不要把「每个 GameObject 各自不同」的运行时状态(如两个敌人当前 HP)放在 SO 上——那是
MonoBehaviour的职责。 - 不要用 SO 当存档;持久化请用 save-systems 一类方案。
- SO 没有
Update,只有OnEnable/OnDisable/OnDestroy。 - 运行时
CreateInstance的对象不会像普通 C# 对象那样被 GC 自动回收,用完需Destroy。 - 项目里已有
*.asset且背后类继承ScriptableObject时,最适合按本技能梳理架构;纯 DTO、从不进资产的可继续用[System.Serializable]。
使用场景
- 策划要在不改场景的前提下批量调整武器数值,需要把 stats 做成可在 Project 里编辑的 `.asset` 配置并由玩法脚本引用
- HUD、玩家控制器与任务系统要共享同一套血量或分数,但不想互相 `FindObjectOfType` 或挂静态单例
- 多个系统要监听「玩家死亡」「拾取物品」等事件,希望用事件通道 SO 发信号而不在代码里硬编码彼此类型
- 战斗或 AI 模块需要维护「当前场景内活跃敌人列表」,想用运行时注册表 SO 统一登记与查询
适合人员
- 负责 Unity 6 项目数据驱动的玩法程序员,要把关卡表、装备参数从场景脚本迁到可复用资产
- 技术策划或关卡策划,需要在编辑器里直接改 SO 配置并立刻让引用该资产的所有 Prefab 生效
- 独立游戏主程在砍单例与交叉引用,想用 FloatVariable / 事件通道模式整理 HUD 与系统通信
- 做卡牌、RPG 或生存建造类项目的前端逻辑工程师,项目里已有大量 `ScriptableObject` 派生 `.asset` 需统一规范