ScriptableObject 子类与 [Serializable] 普通类 核心对比

ScriptableObject 子类与 [Serializable] 普通类 核心对比

核心结论:两者都能被 Unity 序列化,但 ScriptableObject 是 “可独立成文件的资源类”,而 [Serializable] 普通类是 “依附于其他对象的序列化数据容器” —— 一个是 “独立文件”,一个是 “附属数据”。

一、核心相同点(都围绕 Unity 序列化)

  • 都支持 Unity 序列化:
    两者的 public 字段(或带 [SerializeField] 的私有字段)都会被 Unity 按序列化规则处理,能在 Inspector 面板显示、编辑,也能被保存 / 加载;
    比如你代码里的 RoleAnimSetting([Serializable])和 RoleSettingSO(ScriptableObject),它们的字段都能在 Inspector 改值。
  • 都支持复杂数据结构:
    都能包含字符串、数字、列表、数组,甚至嵌套其他带 [Serializable] 的普通类(比如 RoleSettingSO 里嵌套 RoleAnimSetting);
  • 都无需挂载到 GameObject:
    区别于 MonoBehaviour,两者都不需要挂载到场景中的游戏对象上(但 [Serializable] 类常作为 MonoBehaviour/ScriptableObject 的字段存在)。

二、核心差异(最关键的区别)

维度ScriptableObject 子类(如 RoleSettingSO)带 [Serializable] 的普通类(如 RoleAnimSetting)
是否能独立成文件✅ 可以!右键创建后生成独立的 .asset 文件,存在 Assets 目录下,是 Unity 资源体系的一员❌ 不能独立成文件!只能作为其他可序列化对象(如 ScriptableObject/MonoBehaviour)的字段存在,没有自己的独立文件
是否有 GUID/meta 文件✅ 作为 Unity 资源,会生成 .meta 文件,有唯一 GUID,支持资源引用、版本控制❌ 无 GUID/meta 文件,只是 “数据片段”,无法被其他资源直接引用
生命周期 / 内存管理作为资源加载(Resources.Load/AssetBundle.Load),加载后常驻内存(除非手动卸载),全局唯一(同一资源多次加载拿到的是同一个实例)随所属对象的生命周期存在(比如作为 RoleSettingSO 的字段,就随 RoleSettingSO 的加载 / 卸载而存在),每次创建所属对象都会生成新的实例
是否支持编辑器特性✅ 支持 [CreateAssetMenu](创建资源)、[ContextMenu](上下文菜单)等专属特性❌ 不支持编辑器专属特性,仅能作为字段被显示
是否可被资源管理✅ 能被 AssetDatabase(编辑器)、Resources(运行时)管理(加载、删除、查询)❌ 无法被资源管理类直接操作,只能通过所属对象间接访问
运行时修改是否持久化❌ 运行时修改内存副本,停止游戏后丢失(和其他 Unity 资源一样),但编辑器中修改后保存会持久化到 .asset 文件❌ 随所属对象的修改规则:如果所属对象是 ScriptableObject,则编辑器修改保存会持久化;如果是 MonoBehaviour,则保存场景 / 预制体时持久化

三、通俗类比(帮你快速理解)

  • ScriptableObject 子类:像一本 “独立的笔记本”,有自己的封面(.asset 文件)、编号(GUID),可以单独放在书架(Assets 目录)上,随时拿出来看 / 改,是完整的 “资源”;
  • [Serializable] 普通类:像笔记本里的 “一页纸”,没有独立的封面和编号,必须依附于笔记本存在,只能和笔记本一起保存 / 使用,是 “数据片段”。

比如你代码里的逻辑:

  • RoleSettingSO(ScriptableObject)是 “独立笔记本”,生成 RoleSetting.asset 文件;
  • RoleAnimSetting([Serializable])是这本笔记本里的 “一页动画配置纸”,只能存在于笔记本里,不能单独拿出来当一本新笔记本。

四、使用场景对比(该用哪个?)

适合用 ScriptableObject 的场景:

  1. 全局配置数据:比如角色动画配置、游戏全局参数、关卡配置(需要独立成文件,可被多个脚本引用);
  2. 可复用的数据集:比如怪物属性表、道具配置表(不同场景 / 脚本都能读取同一个 .asset 文件);
  3. 编辑器工具数据:比如自定义编辑器的配置(需要独立存储,方便版本控制)。

适合用 [Serializable] 普通类的场景:

  1. 嵌套数据结构:比如 RoleSettingSO 里的 AnimSetting、玩家的属性(血量 / 攻击力)、怪物的掉落物品列表(作为字段依附于其他对象);
  2. 临时数据容器:比如存储一个技能的多个参数(冷却时间、伤害、特效名称),打包成一个类作为 MonoBehaviour 的字段;
  3. 无需独立引用的数据:比如仅在某个脚本内使用的配置,不需要被其他脚本单独加载。

五、关键补充:容易踩的坑

  1. [Serializable] 类不能有无参构造函数?
    不是不能有,而是 Unity 序列化时会忽略自定义构造函数,建议通过字段默认值或 Awake/OnEnable 初始化;
  2. ScriptableObject 能继承 [Serializable] 类吗?
    可以!且推荐这么做(比如你的代码里 RoleSettingSO 包含 RoleAnimSetting),本质是 “独立资源” 包含 “附属数据”;
  3. 两者都不支持哪些序列化?
    都不支持静态字段、私有字段(除非加 [SerializeField])、接口类型、字典(需用第三方工具或自定义序列化)。

总结

  1. 相同点:都支持 Unity 序列化,能在 Inspector 编辑,支持复杂数据结构;
  2. 核心差异:ScriptableObject 是 “独立资源类”,可生成 .asset 文件、有 GUID、能被资源管理;[Serializable] 普通类是 “附属数据类”,无独立文件、依附于其他对象;
  3. 使用原则:需要独立存储、全局复用的用 ScriptableObject;仅作为字段嵌套、临时存储的用 [Serializable] 普通类。

简单说:ScriptableObject 是 “独立的配置文件模板”,[Serializable] 是 “配置文件里的内容模板”—— 前者造文件,后者填内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值