Menu
CoddyTech

Сериализуемые классы

Часть раздела Архитектура игр в Unity путешествия по Unity на Coddy. Урок 18 из 64.

Скрипт со множеством настроек отображается в Inspector длинным плоским списком. Обычный класс C# позволяет сгруппировать их: пометьте его атрибутом [System.Serializable], и поле этого класса будет отображаться как сворачиваемый раздел с именем поля, внутри которого находятся поля класса. Один класс можно использовать для нескольких полей и нескольких скриптов:

[System.Serializable]
public class Stats
{
    public float speed = 2f;
    public int damage = 10;
}

public class Enemy : MonoBehaviour
{
    public Stats normal;
    public Stats enraged;
    private Stats current;

    void Start()
    {
        current = normal;
    }

    void Update()
    {
        transform.Translate(0f, 0f, current.speed * Time.deltaTime);
    }

    public void Enrage()
    {
        current = enraged;
    }
}

В Inspector отображаются два сворачиваемых раздела — Normal и Enraged, в каждом из которых есть Speed и Damage. У каждого Enemy есть собственные два объекта Stats, заполненные в его Inspector, а код обращается к ним как к normal.speed. Unity создаёт эти объекты при загрузке скрипта, поэтому normal никогда не равен null даже без = new Stats(), а начальные значения полей (2 и 10) используются для нового Enemy. Структура работает так же с атрибутом: [System.Serializable] public struct Range { public float min; public float max; }, и, как Vector3, копируется при присваивании.

Этот атрибут необходим, потому что Unity сохраняет только те типы, которым это указано. Без него класс невидим для Inspector: сворачиваемого раздела не будет, заданные там значения не сохранятся, а Unity не создаст объект, поэтому normal.speed вызовет NullReferenceException. Внутри класса действуют обычные правила Inspector: публичные поля или приватные поля с атрибутом [SerializeField], но не свойства и не статические поля.

challenge icon

Задание

Легко

Сгруппируй настройки каждого луча в одной структуре.

  1. Перед Flashlight объяви public struct Beam с общедоступными полями Color color, float range и float angle. Отметь её атрибутом [System.Serializable], чтобы она отображалась в Inspector.
  2. Замени шесть отдельных полей на public Beam wide; и public Beam focused;.
  3. В Apply() задай три значения источника света из focusedOn ? focused : wide.

Нажми «Играть» и пробел: луч достигает кристалла. Затем нажми «Проверить».

Попробуйте сами

using UnityEngine;
using UnityEngine.InputSystem;

public class Flashlight : MonoBehaviour
{
    public Color wideColor = Color.white;
    public float wideRange = 5f;
    public float wideAngle = 60f;
    public Color focusedColor = Color.white;
    public float focusedRange = 10f;
    public float focusedAngle = 30f;
    private bool focusedOn;
    private Light lamp;

    void Start()
    {
        lamp = GetComponent<Light>();
        Apply();
    }

    void Update()
    {
        if (Keyboard.current.spaceKey.wasPressedThisFrame)
        {
            focusedOn = !focusedOn;
            Apply();
        }
    }

    void Apply()
    {
        lamp.color = focusedOn ? focusedColor : wideColor;
        lamp.range = focusedOn ? focusedRange : wideRange;
        lamp.spotAngle = focusedOn ? focusedAngle : wideAngle;
    }
}

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

Потренируйтесь самостоятельно: Песочница Unity