概述

ScriptableObject是什么

是Unity提供的数据配置存储基类,是一个可以存储数据的容器

数据复用

一个子弹对象,每次实例化的时候,N个子弹上都有脚本,脚本内存储子弹的信息,比如速度,攻击力等

这些大量的细粒度对象对内存来说是一定的浪费

我们可以用SO进行数据复用

配置文件

我们可以在unity内部进行数据的配置,避免xml,json等的使用

编辑模式下的数据持久化

在unity编辑器内SO有持久化特性

SO的好处

  1. 在unity内文件配置
  2. 数据复用
  3. 更好的处理数据的多态行为

数据文件的创建

自定义SO数据容器

1
2
3
4
5
6
7
8
9
10
11
12
13
using UnityEngine;
using UnityEngine.Video;

namespace SO
{
public class MyData : ScriptableObject
{
public GameObject obj;
public float speed;
public int atk;
public VideoClip vc;
}
}

我们可以在inspector里关联成员变量,注意,这些只是默认数据

屏幕截图 2023-11-24 150343

这只是一个类,我们还没有创建数据资源文件

创建数据资源文件

方法有两种

为类添加CreateAssetMenu特性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
using UnityEngine;
using UnityEngine.Video;

namespace SO
{
[CreateAssetMenu(fileName = "DefaultMyData",menuName = "MyData",order = 0)]
public class MyData : ScriptableObject
{
public GameObject obj;
public float speed;
public int atk;
public VideoClip vc;
}
}

屏幕截图 2023-11-24 151010

用静态方法创建数据对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
using UnityEditor;
using UnityEngine;

namespace SO
{
public class ScriptableObjectTool
{
[MenuItem("ScriptableObject/CreateMyData")]
public static void CreateMyData()
{
MyData asset = ScriptableObject.CreateInstance<MyData>();

AssetDatabase.CreateAsset(asset,"Assets/Resources/MyDataTest.asset");

AssetDatabase.SaveAssets();

AssetDatabase.Refresh();
}
}
}

点击按钮,即可创建文件

屏幕截图 2023-11-24 154754

数据文件的使用

数据文件的使用

直接在MonoBehaviour类中作为成员使用

  1. 通过Inspector关联使用
  2. 通过Resource.Load取用

SO的生命周期函数

Awake:文件创建时调用

OnDestroy:对象被销毁时调用

OnEnable:创建或加载对象时调用

OnDisable:销毁对象或即将重新加载脚本程序集时调用

OnValidata:编辑器才会调用的函数,unity在加载脚本或者Inspector窗口中更改值时调用

非持久数据

非持久数据指的是不管在编辑器内还是发布后都不会持久化的数据

我们可以根据自己的需求随时创建对应数据对象进行使用

使用SO生成非持久化数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using UnityEngine;

namespace SO
{
public class Test : MonoBehaviour
{
private MyData data;

private void Start()
{
data = ScriptableObject.CreateInstance<MyData>();

Debug.Log(data.atk);
}
}
}

非持久数据的优点

节约硬盘空间,仅在内存中使用

ScriptableObject数据持久化

Json结合SO存储数据

屏幕截图 2023-11-29 132819

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using System.IO;
using UnityEngine;

namespace SO
{
public class SaveManager : MonoBehaviour
{
[SerializeField]private MyData data;

private void Start()
{
var str = JsonUtility.ToJson(data);

File.WriteAllText(Application.persistentDataPath + "/testJson.json",str);

}
}
}
1
{"obj":{"instanceID":22550},"speed":5.0,"atk":5,"vc":{"instanceID":0}}

Json结合SO读取数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
using System.IO;
using UnityEngine;

namespace SO
{
public class SaveManager : MonoBehaviour
{
[SerializeField]private MyData data;

private void Start()
{
var str =File.ReadAllText(Application.persistentDataPath + "/testJson.json");
JsonUtility.FromJsonOverwrite(str,data);
Debug.Log(data.atk);
}
}
}

屏幕截图 2023-11-29 133601

SO应用

  • 配置数据

SO适合做配置文件,因为配置文件一般是只读的,游戏不会修改配置文件

SO不需要第三方软件,比如Excel,Json编辑器等

  • 复用数据

当我们使用大量细粒度的对象时,比如子弹,许多子弹可以共享同一份数据,而不用为每个子弹都分配内存

  • 数据带来的多态行为

  • 使用单例获取数据