Unity14 - ScriptableObject

通过ScriptableObject实现了多个gameObject共享同一套数据(节约内存)、在Unity编辑器Inspector窗口中修改非持久化开发配置(方便)的目的。

目录

ScriptableObject解决的问题

  • 数据复用:批量生成子弹时,所有子弹对象具有相同的成员属性(speed,atk,lifespan等),但每生成一个子弹就要开辟一块内存存储相同的内容,使用ScriptableObject可以让所有子弹共用同一块内存空间来存储这些相同的内容
  • 数据外显:让数据显示在Inspector窗口中,便于修改

创建数据文件

  • 继承:public class MyData : ScriptableObject {}
    • 继承ScriptableObject后在类中public的变量会显示在Inspector窗口中
  • 添加到Create资源菜单:[CreateAssetMenu(fileName="添加后显示在目录上的文件名",menuName="Create菜单显示的名,/分隔多级目录",order=在菜单上显示的顺序)]

使用数据文件

  • 本质是创建了一个类似Material一样的Unity资源文件,内容完全自定义。在go上添加脚本,public一个MyData属性,就可以将创建的自定义资源文件拖上去
  • Resources/AB包/Addressables都支持添加该资源
  • 多个go添加同一个资源时共享一个数据,一处修改多处改变

编辑器中持久化

  • MyData类中public后赋值,每次运行都会运行赋值代码,等效于编辑器中持久化,但发布后不会加载
  • 每次修改都会修改本地文件
    • 不使用本地文件,而是动态创建,实现不读取本地的非持久化
      1
      2
      3
      4
      5
      6
      //与go关联的组件脚本中
      public MyData data;
      void Start()
      {
      data = ScriptableObject.CreateInstance<MyData>();
      }
  • 可以通过保存数据到json/xml等文件实现持久化,但多此一举,不建议

应用

只用不改,可在Unity中编辑,不需要发布,不需要持久化的配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//角色信息
[CreateAssetMenu(fileName="Role",menuName="MyData/Role",order=0)]
public class Role
{
[System.Serialable] //自定义类要显示需要加特性
public class RoleInfo
{
public string name;
public int age;
public bool sex;
public void Show() {
print(name);
print(age);
print(sex);
}
}
public List<RoleInfo> roleList;
}

复用数据

  • 为所有用到的go添加一个包含自定义数据资源属性的脚本组件,调用同一个数据资源

单例模式获取基类

  • 所有的go为了获得该数据,都需要public关联动态CreateInstance<>(),每一个go都需要获取一次。通过建立单例模式获取基类来获取数据,让子类获取数据更方便
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    public class SingleScriptableObject<T>:ScriptableObject where T:ScriptableObject
    {
    private T instance;
    public static T Instance
    {
    get
    {
    //自定义数据资源的路径是 Resources/类名.asset
    if(instance==null){
    instance = Resources.Load<T>("ScriptableObject/" + typeof(T).Name);
    }
    if(instance==null){
    instance = CreateInstance<T>();
    }
    return instance;
    }
    }
    }
  • 所有的自定义数据资源类都可以通过继承SingleScriptableObject<类名>,然后go脚本组件通过访问自定义数据类.Instance获得自定义数据资源的数据