ScriptableObject使用探究
环境信息
Unity 2018.2
.Net 4.x Equivalent
问题描述
在Unity 2017中引入了新类型ScriptableObject,有不少文章提及它可以作为容器保存序列化后的数据,且可以实时修改,实时保存。本次尝试探究该类型在实际生产中的可行性与定位。
尝试流程
- 创建继承于ScriptableObject的数据类Student,内含基础成员变量。
using UnityEngine;
[CreateAssetMenu(menuName="MyAsset/Student")]
public class Student : ScriptableObject
{
public string Name { get; set; } = "Jack";
public int age { get; set; } = 10;
}
-
通过新增菜单项Assets->MyAssets->Student生成asset文件
创建asset菜单
-
创建测试场景UI
测试UI -
运行后尝试修改
尝试修改
示例说明:
- 点击ChangeName按钮会在当前名字后添加*号;
- 点击ChangeAge按钮会在当前年龄上增加1;
-
关闭程序重新运行
结果发现上次修改的结果依然存在,说明实时修改被保存了下来。 -
打包程序烧入设备测试
也同样尝试将Student.asset放入StreamingAssets目录下。但是,如猜测一致,由于在设备上Resources和StreamingAssets目录是只读目录,修改后的结果并没有得到保存。关闭程序后重新运行会发现值又恢复至初始状态。
查阅文档
官方文档上有一段话值得细细研读下。
In a deployed build, however, you can’t use ScriptableObjects to save data, but you can use the saved data from the ScriptableObject Assets that you set up during development.
笔者的理解是:ScriptableObjects这个类型并不推荐在正式的(交付后)运行中保存实时数据,我们可以更多地用它在开发过程中实时地保存调试数据。
如果真的想利用ScriptableObjects在正式运行中保存数据,笔者能想到的一个方式是将该ScriptableObjects Asset打入AB包。初始运行时,将该AB包拷贝入可写目录PersistentDataPath中,后续通过加载AB的形式加载该Asset。笔者没有尝试该方法,是觉得这样加载一个ScriptableObjects Asset的形式已经不如直接在PersistentDataPath读写一个自定义的文件来得简单明了了。当然,如果你定义的ScriptableObjects Asset中有相当多的初始数值,那还是值得一试。
总结
- ScriptableObjects定义为一个不依赖GameObject的保存数据容器。
- ScriptableObjects可以保存成Prefab的资源形式,用于在多个地方共享数据。
- 官方更多的推荐是在开发中利用它的实时性进行数值的调整与保存,在Untiy中可以开发更好的策划数值工具来简化交付流程,以ScriptableObjects Asset的形式来交付客户端的数据表。