Ресурсы данных
Часть раздела Архитектура игр в Unity путешествия по Unity на Coddy. Урок 19 из 50.
В фермерской игре растут морковь и тыквы. Морковь растёт 30 секунд и продаётся за 5 монет, а тыква растёт 90 секунд и продаётся за 40. Эти числа относятся к культуре, а не к отдельному растению: если хранить их в полях Inspector скрипта Plant, у каждой моркови в каждой сцене будет своя копия значений 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] добавляет класс в меню Create окна Project. Щёлкни правой кнопкой мыши в окне Project, выбери Create > Farm > Plant Data, и Unity создаст ассет с именем NewPlant; переименуй его в Carrot, выбери его и введи Carrot, 30 и 5 в его поля в Inspector. Ассет 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.
Задание
СреднеГерой ходит по арене с помощью клавиш со стрелками. Его имя, скорость и цвет — это поля скрипта Hero, и каждый новый герой будет копировать их заново. Перенесите их в ассет:
- В
HeroData.csнапишитеHeroData— ScriptableObject с публичными полямиheroName(строка),moveSpeed(число с плавающей точкой) иcolor(Color). Добавьте ему[CreateAssetMenu]с именем пункта менюHeroes/Hero Data. - В
Hero.csзамените три поля одним публичным полемdataтипа HeroData и используйте значения из ассета там, где скрипт использовал собственные значения.
В проекте есть ассет Knight, созданный с помощью этого меню (Knight, скорость 3, красный цвет), и Inspector помещает его в поле data объекта Hero. Нажмите Play и поводите Knight по арене, затем нажмите Check.
Попробуйте сами
using UnityEngine;
// HeroData: имя, скорость и цвет героя в виде ScriptableObject
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Архитектура игр в Unity
1Компоненты, а не иерархии
Небольшие компонентыБазовый скрипт врагаАбстрактные компонентыСовместная работа компонентовПовторение: модульная турель4Сериализованные данные
Сериализуемые классыСписки в InspectorПеречисления в InspectorПовторение: таблица лута2Интерфейсы в Unity
IDamageableИнтерфейсы и TryGetComponentGetComponentsПовторение: клавиша взаимодействия5ScriptableObjects
Ресурсы данныхХарактеристики оружияОбщие настройкиВолны как данныеПовторение: база предметов