ScriptableObject 的使用

运行结果

可以在 Aseets/Create 创建 “类对象资源”,也可以在 Assets 面板的 “+” 中创建。如果需要在游戏运行时加载可以将它放到 Resources 文件夹中。

创建完成后,生成 “New Script_04_12.asset”,并且点击的话会在 Inspector 面板显示如下。可以看到显示了我们在继承了 ScriptableObject 的类中定义的成员变量( 代码见 Script_04_12.cs )。并且可以在 Inspector 面板修改对应的值。

上述方法是点击一下 Aseets/Create/Script_04_12 创建一个空的 “类对象资源” ,然后需要自己手动在 Inspector面板赋值,这样的话需要大批量的生成这种资源就很麻烦,所以可以在代码中将赋值好,然后只点击一个按钮就可以生成赋值好的资源。代码见 Script_04_12_create.cs

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 文件名:Script_04_12.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu]
public class Script_04_12 : ScriptableObject
{
[SerializeField]
public List<PlayInfo> m_playInfo;

[System.Serializable]
public class PlayInfo
{
public int id;
public string name;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 文件名:Script_04_12_main.cs
// 可以在运行时加载 “类对象资源”,详情如图。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Script_04_12_main : MonoBehaviour
{
private void OnGUI()
{
if (GUILayout.Button("加载Script_04_12"))
{
// New Script_04_12 是通过[CreateAssetMenu],然后在Asset右击新建的。
// 要将 New Script_04_12 放到资源的 Resources 文件夹下面
Script_04_12 script = Resources.Load<Script_04_12>("New Script_04_12");
Debug.LogFormat("加载的 script 第一个元素的 id 为 {0},name 为 {1}", script.m_playInfo[0].id, script.m_playInfo[0].name);
}
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 文件名: Script_04_12_create.cs
// 要放在 Editor 文件夹下。Editor 文件夹位置和数量不限
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class Script_04_12_create
{
[MenuItem("Assets/Create script_04_12")]
static void Create()
{
Script_04_12 script = ScriptableObject.CreateInstance<Script_04_12>();

// 填充数据
script.m_playInfo = new List<Script_04_12.PlayInfo>();

//Script_04_12.PlayInfo info = new Script_04_12.PlayInfo();
//info.id = 10086;
//info.name = "张思";
//script.m_playInfo.Add(info);
//上面可化简为
script.m_playInfo.Add(new Script_04_12.PlayInfo() { id = 10086, name = "张思" });

// 储存数据
AssetDatabase.CreateAsset(script, "Assets/Resources/Create Script_04_12.asset");
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
}

感想

命名规范

雨松大大用的命名规范有点让人迷惑,一开始我以为它是将私有成员变量都使用 m_ 为前缀,然后使用 Pascal 大小写,但是
[SerializeField] public List<PlayInfo> m_playInfo; 就难以解释。

关于 “类对象资源”

这个名字是我自己取的哈哈,因为很好理解,就是类的一个实例化对象被以资源的形式存储。一般有三种操作方式:

  • 在运行时使用 Resources.load<>() 来加载并使用
  • 使用在继承了 ScriptableObject 的类上用 [CreateAssetMenu] 来修饰,但这样创建出来的 “类对象资源” 是空的,需要自己在 Inspector 面板上再赋值
  • 使用 ScriptableObject.CreateInstance<>()AssetDatabase.CreateAssets()AssetDatabase.SaveAssets()AssetDatabase.Refresh() 组合拳,代码中填充好将要保存的 “类对象资源” 的数值之后再保存到 Assets 里面。

markdown 代码高亮

不能用 c-sharp 或者 c# ,应该写成 cs(震惊)