Menu
CoddyTech

Ресурсы данных

Часть раздела Архитектура игр в 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.

challenge icon

Задание

Средне

Герой ходит по арене с помощью клавиш со стрелками. Его имя, скорость и цвет — это поля скрипта 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
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Архитектура игр в Unity