Обобщённые вспомогательные методы
Часть раздела Архитектура игр в Unity путешествия по Unity на Coddy. Урок 35 из 50.
Некоторые вспомогательные методы одинаковы для всех типов: получить компонент или добавить его, выбрать случайный элемент из массива. Обобщённый метод позволяет написать их один раз, указав тип в качестве параметра T, который заполняется при каждом вызове:
public static class Helpers
{
public static T GetOrAdd<T>(this GameObject go) where T : Component
{
if (!go.TryGetComponent(out T found)) found = go.AddComponent<T>();
return found;
}
public static T RandomItem<T>(T[] items)
{
return items[Random.Range(0, items.Length)];
}
}Rigidbody body = crate.GetOrAdd<Rigidbody>();
Color paint = Helpers.RandomItem(colors);
GameObject enemy = Helpers.RandomItem(enemyPrefabs);where T : Component — это гарантия относительно T, которая определяет, что метод может с ним делать. AddComponent принимает только компоненты, поэтому без ограничения компилятор не разрешает go.AddComponent<T>(); с ним подойдёт любой компонент — будь то Rigidbody из Unity или ваши собственные скрипты. Ограничение также даёт доступ ко всем членам Component для T, например .transform и .gameObject. Если у crate уже есть Rigidbody, метод вернёт его, и ничего не будет добавлено.
У RandomItem нет ограничения, потому что он никак не взаимодействует с T: он работает и с цветами, и со строками, и с префабами. При вызове тип обычно не указывают: по colors, массиву Color[], компилятор определяет, что T — это Color. Метод, который принимает IEnumerable<T> вместо T[], принимает и массивы, и Lists, в том числе массивы, которые возвращает FindObjectsByType<T>.
Задание
СреднеИмпульсная башня стоит во дворе. При нажатии Space она посылает импульс: ящики в пределах 4 единиц от неё подбрасывает вверх, а светильники в пределах 4 единиц загораются. Lamp.cs уже готов, в нём есть TurnOn(). Напиши один вспомогательный метод, который находит и те и другие:
- В
Helpers.csнапиши статический классHelpersс обобщённым методомInRange<T>(IEnumerable<T> items, Vector3 center, float range)для любого типа компонента. Он возвращаетList<T>с объектами, расстояние от позиции которых доcenterне превышаетrange. - В
Pulse.cs, когда нажата клавиша Space: каждыйRigidbodyв сцене в пределахrangeот башни получает направленный вверх импульс величинойlift, а каждыйLampв пределахrangeвключается. ИспользуйInRangeдля обоих типов объектов в массивах, которые возвращаетFindObjectsByType.
Нажми Играть, нажми Space, затем Проверить.
Попробуйте сами
using System.Collections.Generic;
using UnityEngine;
// Helpers.InRange<T>: элементы в пределах заданного расстояния от точки
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Архитектура игр в Unity
1Компоненты, а не иерархии
Небольшие компонентыБазовый скрипт врагаАбстрактные компонентыСовместная работа компонентовПовторение: модульная турель4Сериализованные данные
Сериализуемые классыСписки в InspectorПеречисления в InspectorПовторение: таблица лута2Интерфейсы в Unity
IDamageableИнтерфейсы и TryGetComponentGetComponentsПовторение: клавиша взаимодействия5ScriptableObjects
Ресурсы данныхХарактеристики оружияОбщие настройкиВолны как данныеПовторение: база предметов8Переиспользуемый код
Методы расширенияОбобщённый синглтонОбобщённые вспомогательные методыПовторение: FindNearest