Unity ScriptableObject
何为 ScriptableObject
ScriptableObject 是Unity中一个强大的工具,可以将其理解为一个独立于场景和游戏对象的数据容器。其与MonoBehaviour一样都继承自UnityEngine.Object,但最大的区别在于,ScriptableObject不是作为组件挂载在游戏对象上,而是作为项目中的资源文件(.asset)存在的。
ScrtiptableObject 与 MonoBehaviour 的区别
| 特性 | ScriptableObject | MonoBehaviour |
|---|---|---|
| 存在形式 | 项目中的资源文件 (.asset) | 挂载在 GameObject 上的组件 |
| 依赖关系 | 独立存在,不依赖场景 | 必须依附于场景或预制体中的 GameObject |
| 主要用途 | 数据容器、配置管理、系统架构 | 游戏对象的具体行为逻辑 |
| 内存效率 | 高。多个对象可共享同一份数据实例,节省内存 | 低。每个预制体实例化时都会复制一份数据 |
| 生命周期 | 支持 Awake, OnEnable, OnDisable, OnDestroy,没有 Update |
支持完整的生命周期函数,如 Update, FixedUpdate 等 |
什么时候适合使用 ScriptableObject
- 作为共享数据容器: 比如游戏里所有敌人NPC都共享一套属性(生命值、攻击力等),可以将这些属性数据都放在一个EnemyData ScriptableObject中,所有敌人实例都引用它。这样,修改一处配置,所有敌人都会生效,极大节省内存。
- 实现模块化及解耦的架构:事件系统————代替传统的单例或委托,让不同系统间通过ScriptableObject进行通信,彼此完全不需要指导对方存在,极大降低耦合度;可插拔行为————可以将一段逻辑封装在ScriptableObject中,然后像换零件一样,在Inspector中拖拽不同的ScriptableObject来改变一个对象的行为,轻松实现策略模式;全局变量————把一些全局状态做成ScriptableObject资源,任何脚本都可以引用和修改它,并且修改是跨场景共享的,省去了用静态类或DontDestroyOnLoad 的麻烦。
- 作为团队协作和设计师友好的配置工具:因为ScriptableObject本身就是资源文件,策划或美术同学可以直接在Inspector面板上修改数值、调整配置,无需接触任何代码,让工作更流畅、减少人为错误的风险。
如何使用 ScriptableObject
创建自己的 ScriptableObject 类
创建一个继承自 ScriptableObject 的C#脚本,并使用[CreateAssetMenu]特性,这样就能通过Unity的 Assets > Create 菜单来生成资源文件了。
using UnityEngine;
[CreateAssetsMenu(fileName = "Audio Settings" , menuName = "Game Settings/Audio Setting")]
public class AudioSetting : ScriptableObject
{
public float audio_Volume;
public float audio_Range;
public float audio_Pitch;
}
生成并使用资源文件
在Unity编辑器中右键点击Assets文件,选择Create > Game Settings > Aduio Setting 就能生成一个.asset文件,然后就可以在此文件的Inspector中填写具体数值了。
在 MonoBehaviour 中引用 ScriptableObject
最后在我们的游戏逻辑脚本中,声明一个公共字段来引用此资源,像拖拽预制体一样拖进去就能使用了。
注意事项
- SO在运行时是一个可读写的内存对象,但不具备持久化能力(修改不会保存到磁盘),如果需要持久化,必须配合PlayerPrefs、文件系统或数据库。
- 编辑器下的保存:在编辑器的 Play Mode 中修改 ScriptableObject 的值,退出 Play Mode 后这些修改会保留。如果你想通过编辑器脚本修改并保存它,需要调用 EditorUtility.SetDirty 来标记数据已改动。
ScriptableObject 和 预制体 的配合使用
| 可以参考以下表格: | 层级 | 用什么 | 存什么 |
|---|---|---|---|
| 数据层 | ScriptableObject | 数值、配置、所有变化频繁的内容 | |
| 表现层 | Prefab | 模型、动画、碰撞体、不变的组件结构 | |
| 逻辑层 | MonoBehaviour | 行为逻辑(巡逻、攻击、死亡) |

