Паттерн «Команда»
Паттерн «Команда»
Вместо прямого вызова метода паттерн «Команда» позволяет инкапсулировать один или несколько вызовов методов в «объекте команды».
Затем объекты команд сохраняются в коллекции, например в очереди или стеке, которая служит небольшим буфером. Это дает дополнительный контроль над выполнением каждой команды. Типичные сценарии включают воспроизведение последовательности действий с заданными интервалами и поддержку их отмены.
Вероятно, вы уже встречали этот прием в любимых игровых жанрах: - В стратегии в реальном времени паттерн «Команда» можно использовать, чтобы помещать в очередь действия юнитов и зданий. Игра будет выполнять команды для зданий по мере появления ресурсов, а для юнитов - последовательности перемещений. - В пошаговой стратегии игрок может выбрать юнита, а затем сохранить его перемещения или действия в очереди либо другой коллекции. В конце хода игра выполнит все команды из очереди игрока. - В головоломке паттерн «Команда» позволяет игроку отменять и повторно выполнять действия.
- В файтинге определенная последовательность нажатий кнопок или движений стика геймпада может запускать комбо и специальные приемы. Для реализации паттерна «Команда» можно использовать ScriptableObject. Например, можно создать команду, задающую перемещение Transform. Если каждое действие обернуть в отдельный объект, управлять им становится проще. Сначала определите интерфейс ICommand с методами Execute и Undo. Вместо интерфейса также можно использовать абстрактный класс:
public interface ICommand {
public abstract void Execute();
public abstract void Undo();
}Затем реализуйте интерфейс ICommand в ScriptableObject. Каждый объект команды получает собственные реализации методов Execute и Undo.
<<интерфейс>>
реализует
Реализация паттерна «Команда» с помощью ScriptableObject
После этого MonoBehaviour или ScriptableObject может определить буфер команд, содержащий объекты команд. В качестве буфера подойдет коллекция: список, стек, массив или очередь. <<интерфейс>>
зависит
Объект верхнего уровня
реализует
Объект нижнего уровня
CommandManager хранит коллекцию объектов ICommand.
Такая простая структура позволяет выполнять команды по очереди. Представьте обучающий эпизод или кат-сцену, в которой GameObject выполняет заданную последовательность действий или анимаций. Паттерн «Команда» отлично подходит для этой задачи. Каждая команда является отдельным объектом, поэтому их легко менять местами. Достаточно выбрать способ организации CommandBuffer: - Если использовать стек, при выполнении помещайте команды в него. При отмене извлекайте команду из основного стека и помещайте в отдельный стек повторного выполнения.
- Если используется список или массив, отслеживайте индекс текущей команды. При отмене уменьшайте индекс, а при повторном выполнении увеличивайте. Один из вариантов реализации отменяемого перемещения показан в классах MoveCommandSO и CommandManager из примера проекта. В простой обучающей сцене подписи к элементам игрового поля объясняют правила игры. Нажмите кнопку Next («Далее»), чтобы перейти к следующему пояснению. Кнопка Back («Назад») позволяет просматривать инструкции в обратном порядке.
Попадите мячом за ракетку соперника и наберите больше очков!
КАК ИГРАТЬ ДВИЖЕНИЕ РАКЕТОК
НАЗАД
ДАЛЕЕ
P1: W или S
P2: ВВЕРХ/ВНИЗ
Кнопки Назад и Далее
Простая реализация паттерна «Команда».
Подробнее о паттерне «Команда» можно узнать из электронной книги «Повышаем уровень кода с паттернами проектирования и SOLID». Также ознакомьтесь с публикацией сообщества «Паттерн "Команда" с ScriptableObject», где показана реализация этого паттерна с помощью ScriptableObject.
ScriptableObject или классы C#? Выбирая архитектуру кода для проекта, важно учитывать навыки и предпочтения команды, а также требования игры к производительности. Одним дизайнерам удобнее работать интерактивно в редакторе Unity, а другим полностью в коде C#.
Учитывайте эти факторы, чтобы с кодовой базой было удобно работать всем участникам команды. Ни один паттерн не подходит абсолютно для всех задач, поэтому перед внедрением тщательно оцените его преимущества и недостатки. Помните: «правильная» архитектура кода просто та, которая лучше всего подходит вашей команде и проекту.