【Unity/笔记】认识ScriptableObject

ScriptableObject

  • ScriptableObject
    一个继承自UnityEngine.Object且字段能够被序列化的类
    也就是说需要用到命名空间UnityEngine
  • VS MonoBehaviour
    我们知道一般继承自MonoBehaviour的脚本组件可序列化的字段都能在Inspector中显示出来,ScriptableObject也可以,当相比之下它不必挂载在某个游戏对象上。
    关于MonoBehaviour有以下几点:

    1. 运行时修改的数据不会在退出运行时保存下来。
    2. 接收Unity的回调函数调用
    3. 运行时需要挂载在游戏对象上
    4. 它的实例被存在scene和prefabs中。
    5. 支持序列化,能在Inspector面板中显示数据。

    关于ScriptableObject:

    1. 运行时修改的数据能够在退出运行时保存下来。
    2. 不接收大多数回调调用(只有Awake、OnEnable、OnDestroy、OnDisable)
    3. 运行时不必依附于指定游戏对象
    4. 每个不同的实例能被存储在各自的文件中。
    5. 同上
  • 基本使用方式

    1. 创建一个派生自ScriptableObject的类叫做MyScriptableObjClass
    2. 添加特性[CreateAssetMenu(menuName =”CreatAM”)]
    3. 右键Create 点击CreatAM,目录下会产生一个新的asset文件,可以命名为MyScriptableObj,该文件存储了MyScriptableObjClass的实例以及其中的数值。
    4. 在其它脚本中使用public MyScriptableObjClass scriptableObj;以使用类型引用的方式将之前的实例添加上去。
  • 为什么使用
    大量创建同一个继承MonoBehaviour的脚本时,脚本中的数据都会复制一份, 我们知道Unity存储场景和预制体时几乎对所有东西都会使用序列化。
    包括每个组件(Component)、 每个游戏对象(GameObject)、 包括每个公有(public)字段,而且不会检查重复数据,不会进行数据压缩,数据越多读写就越慢。

    相比之下,使用的ScriptableObject的引用就只不过是一个小小的属性。由于使用的只是引用,因此原本需要进行复制的数据越多ScriptableObject的优势就越大。

  • 如何创建

    1. 创建新实例
      使用ScriptableObject下的静态方法CreatInstance();
      使用这种方式可以进行动态创建,在编辑模式和运行模式下都可以。
      使用new来创建实例不被允许,编辑器会发出警告。

    2. 将一个实例保存到asset文件

      1. 创建一个新的Asset文件:UnityEditor下的 AssetDatabase.CreatAsset(Object obj,string path);其中obj应是一个继承了ScriptableObject的类型实例,而path则是”Assets/xxx.asset”。当然这个方法也支持动态创建其它资源文件如材质.mat文件。
      2. 使用AssetDatabase.AddObjectToAsset,类似于1,不过貌似这个方法有些BUG没解决
      3. 之前所说CreateAssetMenu 的方式
  • OnEnable

    • 当一个ScriptableObject实例化或一个被加载时
    • 在ScriptableObject.CreateInstance执行期间
    • 编辑器重新编译时(如修改脚本编辑器每次重新编译及进入退出运行模式时)
  • OnDestroy

    • 在实例被销毁之前,或者在明确调用Destroy方法与在调用OnEnable之后的期间。
  • OnDisable

    • 在实例将要被销毁时
      在OnDestroy调用之前和执行Destroy方法的期间。
      在实例对象将要被垃圾回收之前。
    • 编辑器重新编译时
  • 生命周期

    当它是被绑定到.asset文件或者AssetBundle等资源文件中的时候,它就是persistent的,这意味着,它可以通过Resources.UnloadUnusedAssets来被unload出内存,可以通过脚本引用或其他需要的时候被再次load到内存
    如果是通过CreateInstance<>来创建的,它就是非persistent的,这意味着它可以通过GC被直接destroy掉(如果没有任何引用的话)
    如果不想被GC的话,可以使用HideFlags.HideAndDontSave

    需要注意的是,在编辑器模式下尽量不要通过CreateInstance创建实例,如果要清除编辑器模式下未绑定Asset文件的实例可以将引用都去掉再进入运行状态让GC自动回收或者使用UnloadUnusedAssets释放。

    总结来说

    1. Destroy或DestroyImmdiate销毁
    2. 无引用时可通过GC回收
    3. 使用Resource.UnloadUnusedAssets或者切换场景
  • 可以用在哪些地方

    1. 可以持久化数据
    2. 可用于配置静态数据,便于数据共享
    3. 能提供通用方法或者插槽功能。
    4. 管理对象并提供一些功能,对象包括且不限于资源、游戏对象等
    5. 解决一些多态问题。
    6. 其它

参考资料:
1. 冯乐乐—ScriptableObject的介绍
2. Unite ‘17 Seoul- ScriptableObjects What they are and why to use them

你可能感兴趣的:(Unity)