Сериализуемые классы
Часть раздела Архитектура игр в 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], но не свойства и не статические поля.
Задание
ЛегкоСгруппируй настройки каждого луча в одной структуре.
- Перед
Flashlightобъявиpublic struct Beamс общедоступными полямиColor color,float rangeиfloat angle. Отметь её атрибутом[System.Serializable], чтобы она отображалась в Inspector. - Замени шесть отдельных полей на
public Beam wide;иpublic Beam focused;. - В
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
1Компоненты, а не иерархии
Небольшие компонентыБазовый скрипт врагаАбстрактные компонентыКомпоненты работают вместеПовторение: модульная турельПовторение: спаренная пушка4Сериализованные данные
Сериализуемые классыСписки в инспектореПеречисления в инспектореПовторение: таблица добычиПовторение: определяем добычу2Интерфейсы в Unity
IDamageableИнтерфейсы и TryGetComponentGetComponentsПовторение: клавиша взаимодействияПовторение: ближайший в пределах досягаемости5ScriptableObjects
Ресурсы данныхХарактеристики оружияОбщие настройкиСохраняем ветерВолны как данныеПовторение: база предметовПовторение: покупка в магазинеПотренируйтесь самостоятельно: Песочница Unity