mcpField
U
unity-scriptableobjects

unity-scriptableobjects

github.com/gamedev-skills开发5.4k6.3k 次安装今天更新
代码仓库

关于 unity-scriptableobjects

unity-scriptableobjects 是面向 Unity 6.3 LTS 项目的架构技能,使用 ScriptableObject 资产管理共享数据并解耦系统。适用于可由设计师编辑的配置、事件通道和运行时对象注册表。

主要功能

  1. 01创建共享数据资产
  2. 02使用事件通道解耦系统
  3. 03构建运行时对象注册表
  4. 04通过资产引用共享配置
  5. 05处理运行时变更与重置

适用场景

  1. 01配置武器属性或关卡数据
  2. 02让不同系统通过事件通信
  3. 03追踪运行中的对象集合
  4. 04避免用单例管理共享数据

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/gamedev-skills/awesome-gamedev-agent-skills --skill unity-scriptableobjects

安装后在 Claude Code 中输入/unity-scriptableobjects确认已加载。

附带文件references/event-channels.md

详细介绍

Unity ScriptableObject 架构

使用 ScriptableObject 资源存储共享数据,在 Unity 6.3 LTS 中解耦系统——配置、事件通道和注册表都作为项目资源存在,而不是硬编码到场景或单例中。目标版本为 Unity 6.3 LTS (6000.3)。

适用场景

  • 需要可由设计师编辑的配置(武器属性、关卡数据)、在无关系统之间共享同一个值、通过事件通道解耦发送方与监听方,或构建活动对象的运行时注册表,且不想使用 static/单例管理器时。
  • 项目包含由 : ScriptableObject 类支持的 *.asset 数据文件时。

不适用场景: 因 GameObject 而异的每实例运行时状态(这类状态应放在 MonoBehaviour 上)——ScriptableObject 资源会被所有引用它的对象共享。将玩家进度保存到磁盘 → save-systems。永远不需要作为资源的普通 DTO 可以直接使用 [System.Serializable] 类。

核心工作流

  1. 定义类,使其继承自 ScriptableObject,并添加 [CreateAssetMenu] 标记,让设计师可以从 Assets 菜单创建实例。
  2. 在 Project 窗口中创建一个或多个 .asset 实例;每个实例都是一份共享且命名的数据,可通过 [SerializeField] 字段引用。
  3. 引用,而非复制。 MonoBehaviour 持有对资源的引用;它们看到的都是同一份数据,因此修改资源会影响所有使用者。
  4. 实现解耦时,将 信号 和 共享变量 建模为 ScriptableObject:HUD 读取、玩家写入的 "FloatVariable";玩家触发、多个系统监听的 "event channel"。双方都不引用对方。
  5. 如果在运行期间修改了资源,请在 OnEnable 中重置运行时改动,因为在运行时于 Editor 中所做的编辑会保留在资源上(这是“我的值在运行后变了”的常见原因)。
  6. 验证:在 Play 模式下检查资源值,并确认使用者会作出响应。

模式

1. 配置/数据资源
using UnityEngine;

[CreateAssetMenu(fileName = "WeaponData", menuName = "Game/Weapon Data", order = 0)]
public class WeaponData : ScriptableObject
{
    public string displayName = "Pistol";
    public int    damage = 10;
    public float  fireRate = 0.25f;
    public GameObject projectilePrefab;
}
public class Weapon : MonoBehaviour
{
    [SerializeField] private WeaponData data;   // assign the shared asset in the Inspector
    private void Fire() => Debug.Log($"{data.displayName} for {data.damage}");
}
2. 共享运行时变量(解耦生产者与使用者)
[CreateAssetMenu(menuName = "Game/Float Variable")]
public class FloatVariable : ScriptableObject
{
    [SerializeField] private float initialValue;
    [System.NonSerialized] public float runtimeValue;   // not saved to the asset

    private void OnEnable() => runtimeValue = initialValue;  // reset each play session
}
// Player writes playerHealth.runtimeValue; the HUD reads it — neither references the other.
3. 在运行时创建实例(不是磁盘上的资源)
// For transient SO data you build in code (e.g. a generated config).
var temp = ScriptableObject.CreateInstance<WeaponData>();
temp.damage = 25;
// ...use temp...  Destroy(temp);   // clean up runtime-created instances

注意事项

  • 在运行时编辑 SO 会在 Editor 中保留——你在 Play 期间修改的值,在停止后仍会保留在资源上。请将可变运行时状态放在 [NonSerialized] 字段中,并在 OnEnable 中重置,否则可能造成意外。(在 构建版本 中,资源编辑不会跨启动保留。)
  • 禁用 Domain Reload 会跳过你的 OnEnable 重置——启用 Enter Play Mode Options 并关闭 Reload Domain(Unity 6.3 LTS 的快速迭代设置)时,已加载的 SO 在按下 Play 时不会重新创建,因此不会触发 OnEnable,runtimeValue 会保留上次会话中的值。请改为通过 ISerializationCallbackReceiver 或场景加载钩子显式重置,而不要只依赖 OnEnable。
  • 不要期待每个对象拥有独立状态——每个引用都指向 同一个 资源。如果两个敌人需要不同的当前 HP,请将 HP 存储在 MonoBehaviour 上,而不是共享 SO 中。
  • 没有逐帧生命周期——ScriptableObject 有 OnEnable/OnDisable/OnDestroy,但没有 Update。不要期待逐帧回调。
  • 不要将 SO 用作存档文件——它们是创作资源,不用于运行时持久化;请改用 save-systems 保存进度。
  • 不要泄漏 CreateInstance 对象——运行时创建的实例不像普通 C# 对象那样由垃圾回收器回收;使用完毕后请调用 Destroy 销毁它们。

参考资料

  • 关于事件通道模式(GameEvent SO + 监听器、类型安全的负载)和运行时集合/注册表(活动敌人的共享列表),请阅读 references/event-channels.md。
  • 主要文档:Unity Manual“ScriptableObject”(/Manual/class-ScriptableObject.html)以及 ScriptReference/ScriptableObject、ScriptReference/CreateAssetMenuAttribute。

相关技能

  • unity-csharp-scripting — 使用这些资源的 MonoBehaviours。
  • save-systems — 将状态持久化到磁盘(这不是 SO 的用途)。
  • card-game / rpg / survival-crafting — 依赖 SO 驱动数据的游戏类型。

评论

支持 Markdown