【Unity】ScriptableObject的介绍

写在前面

我竟然最近两天才知道Unity中ScriptableObject的存在……

看了下ScriptableObject的一些介绍,最大的优点感觉有三点:

  • 把数据真正存储在了资源文件中,可以像其他资源那样管理它,例如退出运行也一样会保持修改
  • 可以在项目之间很好的复用,不用再制作Prefab那样导入导出
  • 在概念上有很好的fit,强迫症患者的福音

看了下感觉有很多东西都可以用它。之前的做法一般都是[Serializable]一个class,然后在面板里配数据,做成prefab,但这种方法没有上面的三个优点。感觉今后如果有类似通过Serializable + Class + Prefab实现存储数据的想法的时候,都应该先考虑下能不能用ScriptableObject做成一个真正的资源文件。

当然了,ScriptableObject还有很多可以应用的地方,例如跟多态结合起来可以做各种特效、音效、技能、对话的资源配置文件。当然不用ScriptableObject也是可以完成这些需求的,感觉ScriptableObject提供了一种更优雅的实现方法。

下面的内容主要参考以下资料:

MonoBehaviour Tyranny

这里写图片描述

为什么某些情况下使用MonoBehaviour很不好:

  • 运行时刻修改了数据一退出就全部丢失了。
    • 这个深有感触,目前都是靠Copy Component Values来解决,很麻烦。其实有这样的需求的时候大部分就说明这个脚本存储的是很多数据,就应该考虑使用ScriptableObject,而不是MonoBehaviour。说到底是因为这些对象不是Assets
  • 当实例化新的对象的时候,这个MonoBehaviour也在内存中多了一份实例,浪费空间
  • 在场景和项目之间很难共享
  • 在概念上就很难定义这种对象,明明是为了存储一些数据和设置等,但却要作为一个Component附着在Gameobject或Prefab上,不能独立存在

为什么使用C#的statics也无法解决这个问题:

  • 一旦退出运行仍然会重置所有数据
  • 需要自己进行serialsation,而且不容易引用其他Unity对象(因为有Static限制)
  • 显示面板也需要我们自己实现,很麻烦

为什么Prefabs也不行:

  • Prefab的确可以在项目和场景之间贡献,但很容易被搞得乱七八糟,我们只需要实例化一个prefab,然后就可以随意更改数据了
  • 会有额外的一些Component,但其实我们只是想要存储数据而已,这些没有任何意义
  • 仍然在概念上不能更好的fit

ScriptableObject是我们的rescue!

  • 在内部实现上它仍然继承自MonoBehaviour,但它不必附着在某个对象上作为一个Component
  • 我们也不能(当然初衷就是不愿意)把它赋给Gameobject或Prefab
  • 可以被serialised,而且可以自动有类似MonoBehavior的面板,很方便
  • 可以被放到.asset文件中,也就是说我们可以自定义asset的类型。Unity内置的asset资源有材质、贴图、音频等等,现在依靠ScriptableObject我们可以自定义新的资源类型,来存储我们自己的数据
  • 可以解决某些多态问题

这里写图片描述

ScriptableObject是如何解决我们的问题的:

  • ScriptableObject的数据是存储在asset里的,因此它不会在退出时被重置数据,这类似Unity里面的材质和纹理资源数据,我们在运行时刻改变它们的数值就是真的改变了
  • 这些资源在实例化的时候是可以被引用,而非复制
  • 类似其他资源,它可以被任何场景引用,即场景间共享
  • 在项目之间共享
  • 没有其他多余的东西,例如多余的Component

当然ScriptableObject也有一些缺点:

  • 很少的回调函数
    • OnEnable
    • OnDisable
    • OnDestroy
  • 真正意义上的共享,因此一旦修改数据都真的修改了

总结:其实说明白点,ScriptableObject的优点和缺点都是因为它表现起来就像一个类似材质、纹理等类型的资源,存在于Assets文件夹下,只有唯一实例

如何使用

非常简单,只需要把平时的继承自MonoBehaviour改成ScriptableObject即可:

基本使用

using UnityEngine;

[CreateAssetMenu(menuName="MySubMenue/Create MyScriptableObject ")]
public class MyScriptableObject : ScriptableObject
{
    public int someVariable;
}

其中,CreateAssetMenu可以让我们在资源创建菜单中添加创建这个ScriptableObject的选项,类似创建脚本、材质等其他资源。

我们也可以在脚本中动态创建一个ScriptableObject:

ScriptableObject.CreateInstance<MyScriptableObject >();

这会在内存中创建一个新的实例,用作临时修改等用途,然后在不使用的时候可以让GC回收。

回调函数

评论 42
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值