数据资产
本课属于 Coddy Unity 学习旅程的“Unity 游戏架构”单元。第 23 课,共 64 课。
农场游戏里种植胡萝卜和南瓜。胡萝卜需要生长 30 秒,售价 5 枚金币;南瓜需要生长 90 秒,售价 40 枚金币。这些数值属于作物,而不是某一株植物:如果把它们作为 Plant 脚本中的 Inspector 字段,每个场景中的每株胡萝卜都会各自保存一份 30 和 5,修改时就得逐个查找。ScriptableObject 会把这类数据保存在一个资源中。资源是项目中的文件,任意数量的对象都可以引用它。它的类继承自 ScriptableObject,而不是 MonoBehaviour:
using UnityEngine;
[CreateAssetMenu(fileName = "NewPlant", menuName = "Farm/Plant Data")]
public class PlantData : ScriptableObject
{
public string plantName;
public float growTime;
public int sellPrice;
}[CreateAssetMenu] 会将这个类添加到 Project 窗口的 Create 菜单中。在 Project 窗口中右键,选择 Create > Farm > Plant Data,Unity 就会创建一个名为 NewPlant 的资源;将它重命名为 Carrot,选中它,然后在 Inspector 中的字段里输入 Carrot、30 和 5。创建 Pumpkin 资源的方法也相同。这个类要放在以类名命名的文件 PlantData.cs 中,就像 MonoBehaviour 一样。
行为仍然保存在 MonoBehaviour 中,并添加一个类型为该资源的字段。将 Carrot 资源拖到这个字段上,脚本就能通过它读取这些数值:
public class Plant : MonoBehaviour
{
public PlantData data;
private float age;
void Update()
{
age += Time.deltaTime;
if (age >= data.growTime)
{
Debug.Log(data.plantName + " is ready, worth " + data.sellPrice);
enabled = false;
}
}
}ScriptableObject 不属于任何 GameObject,也不在任何场景中。它没有 Transform,Unity 也不会调用它的 Update 或 Start:它负责保存数据,Plant 负责保存行为。如果 200 株胡萝卜都引用同一个 Carrot 资源,将它的 growTime 设为 25 就会同时更改这 200 株胡萝卜。在代码中,使用 ScriptableObject.CreateInstance<PlantData>() 创建实例,绝不能使用 new。
挑战
中等将英雄的设置移入数据资源。
- 在
HeroData.cs中,编写public class HeroData : ScriptableObject,并声明公共的string heroName、float moveSpeed和Color color。 - 将
[CreateAssetMenu(menuName = "Heroes/Hero Data")]放在它上面一行。 - 在
Hero.cs中,用public HeroData data;替换这三个字段,并改为读取data.heroName、data.moveSpeed和data.color。
按下“开始”:红色骑士会以速度 3 行走。然后按“检查”。
亲手试试
using UnityEngine;
// HeroData:用 ScriptableObject 保存英雄的名字、速度和颜色
Unity 游戏架构中的所有课
自己练习: Unity 在线编辑器