[Программирование, Проектирование и рефакторинг, Разработка игр, Unity] Подпишись, чтобы не пропустить — События
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Событийно-ориентированный подход к разработке позволяет естественным изолировать реализацию бизнес-логики приложения от пользовательского интерфейса. Как в большей степени Unity-разработчик, я буду демонстрировать все именно в контексте геймдева. В прошлой статье я показал, как конечные автоматы позволяют организовать бизнес-логику в виде системы состояний со строго обозначенным поведением. Сегодня мне бы хотелось уделить внимание тому, как именно автомат должен взаимодействовать с игровыми объектами и управлять состоянием сцены.В примерах в статье про автоматы я использовал следующую конструкцию:
Game.Event.Invoke("joystick_updated", input);
По структуре вызова функции можно понять, что есть некоторый статический класс Game, предоставляющий глобальный доступ к своим полям, что очень удобно при небольших размерах проекта. Вот часть его содержимого:
public static class Game
{
public static FSM Fsm = new FSM();
public static EventManager Event = new EventManager();
public static ObservableData Data = new ObservableData();
...
В этих примерах можно увидеть некоторые вольности в деталях реализации. При масштабировании проекта, например, придется отказаться от статического контекста и на основе класса Game реализовать компоненты, назовем их претенциозно MonoBehaviourPro с подобной структурой для сложных подсистем, и передавать ее в качестве контекста автомату и компонентам этих подсистем. Я намеренно сглаживаю эти углы для большей наглядности примера. Сегодня мы рассмотрим класс с многострадальным названием EventManager, так как он является зависимостью ObservableData и без него мы не сможем двинуться дальше. По ссылке можно увидеть полную реализацию класса EventManager, принцип его работы предельно прост. Мы храним список делегатов c произвольной сигнатурой, подписанных на события со строковым ключом. Важно, что мы работаем с Generic-структурой, поэтому следует помнить о Type safety. Тип аргумента при отправке события должен соответствовать сигнатурам функций, подписанных на него. Также, можно заметить, что EventManager отдельно хранит binds и binds_global и имеет отдельный интерфейс для работы с ними. Это реализация, специфичная для Unity. Дело в том, что там существует система сцен, позволяющая подгружать или выгружать сцены и объекты. И разница между этими двумя словарями в том, что первый очищается при выгрузке сцены. В идеальном мире мы всегда подписываем объект в Awake и отписываем его в OnDestroy. В таком случае можно было бы обойтись одним binds, не очищая его никогда. Каждый объект подписывается и отписывается в рамках своего жизненного цикла и разве что при переходе между сценами происходило бы немного лишней работы над поштучным отписыванием выгружаемых объектов. Но такой подход не прощает ошибок, выгруженный подписчик в лучшем случае сразу сломает вызов делегата и будет найдена, а в худшем - станет причиной утечки памяти. Так что, в качестве "защиты от дурака" лучше при переходе явно отписывать все, что не было обозначено как Global.Итак, интерфейс EventManager cводится к 5 методам:
public void Bind<T>(string name, Action<T> ev)
public void BindGlobal<T>(string name, Action<T> ev)
public void Unbind<T>(string name, Action<T> ev)
public void UnbindGlobal<T>(string name, Action<T> ev)
public void Bind(string name, Action ev)
public void BindGlobal(string name, Action ev)
public void Unbind(string name, Action ev)
public void UnbindGlobal(string name, Action ev)
public void Invoke<T>(string name, T arg)
public void Invoke(string name)
Мы можем подписываться на события и отправлять их. И все это с аргументом произвольного типа. В примере из статьи про FSM мы передавали ввод с джойстика в автомат и, если состояние предусматривает такую возможность, передавали в EventManager событие изменения положения джойстика , на которое может подписаться компонент, управляющий положением игрока(Или потомок MonoBehaviourPro, какой нибудь PlayerController, который передаст информацию о вводе в свой автомат, и если игрок в состоянии SPlayerDriving , будет передавать ввод с джойстика уже автомобилю, за рулем которого он сидит, а если в SPlayerClimbing, джойстик будет двигать игрока перпендикулярно нормали плоскости, по которой он движется, с соответствующей анимацией. Но это уже более сложные примеры, не будем на этом задерживаться). Или же, на входе в состояние игры SWin мы можем отправить событие level_done, а на него подписать анимацию экрана победы, конфетти, и чего там еще ваш ГД придумает.Некоторые события, не влияющие на игровой процесс, такие как включение-выключение звука, вполне можно обрабатывать в обход автомата, отправляя событие напрямую с кнопки, и принимая его классом-оберткой PlayerPrefs, как бы он ни был устроен. Тут я призываю вас руководствоваться здравым смыслом и собственным чувством прекрасного. Таким образом, автомат в процессе своей работы может отправлять события подписавшимся на них объектам через EventManager. В следующей статье я расскажу о возможностях, предоставляемых классом ObservableData в связке с описанными инструментами.Эта статья - вторая в серии:
- Разделяй и властвуй — Использование FSM в Unity
- Подпишись, чтобы не пропустить — События
===========
Источник:
habr.com
===========
Похожие новости:
- [Программирование, Java] Сравнение Java-записей, Lombok @Data и Kotlin data-классов (перевод)
- [Семантика, Облачные вычисления, Хранение данных] Дата-центрическая архитектура: «волшебная пуля» от интеграционных проблем
- [C, Программирование микроконтроллеров, Matlab] Лаконичная реализация конечных автоматов в Matlab, Octave, C
- [Тестирование IT-систем, PHP, Программирование] «Дело было вечером, делать было нечего» или краткая история о сравнении производительности языков программирования
- [.NET, Разработка игр, Unity] Предупреждение для разработчиков о грядущих критических изменениях в движке (перевод)
- [Программирование, Java, Kotlin] Увеличиваем throughput приложения в 2 раза или неблокирующая работа с Elasticsearch с использованием Kotlin coroutines
- [PostgreSQL, Программирование, SQL, Администрирование баз данных] Опыт хранения IP-адресов в PostgreSQL
- [Программирование, Разработка игр, Игры и игровые приставки, Интервью] Подкаст «Хочу в геймдев» #4 — текстовая версия
- [Open source, Программирование микроконтроллеров, DIY или Сделай сам, Электроника для начинающих] я подарю тебе маленькую вселенную
- [Разработка игр, Дизайн игр, История IT, Игры и игровые приставки] ОТЦЫ ИГРОВОЙ ИНДУСТРИИ. КРИС АВЕЛЛОН [ЧАСТЬ 2/3]. OBSIDIAN ENTERTAINMENT
Теги для поиска: #_programmirovanie (Программирование), #_proektirovanie_i_refaktoring (Проектирование и рефакторинг), #_razrabotka_igr (Разработка игр), #_unity, #_shablony_proektirovanija (шаблоны проектирования), #_unity3d, #_gamedev, #_arhitektura_prilozhenij (архитектура приложений), #_programmirovanie (
Программирование
), #_proektirovanie_i_refaktoring (
Проектирование и рефакторинг
), #_razrabotka_igr (
Разработка игр
), #_unity
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 04:16
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Событийно-ориентированный подход к разработке позволяет естественным изолировать реализацию бизнес-логики приложения от пользовательского интерфейса. Как в большей степени Unity-разработчик, я буду демонстрировать все именно в контексте геймдева. В прошлой статье я показал, как конечные автоматы позволяют организовать бизнес-логику в виде системы состояний со строго обозначенным поведением. Сегодня мне бы хотелось уделить внимание тому, как именно автомат должен взаимодействовать с игровыми объектами и управлять состоянием сцены.В примерах в статье про автоматы я использовал следующую конструкцию: Game.Event.Invoke("joystick_updated", input);
public static class Game
{ public static FSM Fsm = new FSM(); public static EventManager Event = new EventManager(); public static ObservableData Data = new ObservableData(); ... public void Bind<T>(string name, Action<T> ev)
public void BindGlobal<T>(string name, Action<T> ev) public void Unbind<T>(string name, Action<T> ev) public void UnbindGlobal<T>(string name, Action<T> ev) public void Bind(string name, Action ev) public void BindGlobal(string name, Action ev) public void Unbind(string name, Action ev) public void UnbindGlobal(string name, Action ev) public void Invoke<T>(string name, T arg) public void Invoke(string name) - Разделяй и властвуй — Использование FSM в Unity - Подпишись, чтобы не пропустить — События =========== Источник: habr.com =========== Похожие новости:
Программирование ), #_proektirovanie_i_refaktoring ( Проектирование и рефакторинг ), #_razrabotka_igr ( Разработка игр ), #_unity |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 04:16
Часовой пояс: UTC + 5