Почти каждый проект, над которым я работал, имел замысловатый дизайн системы пользовательского интерфейса. Большинство платформ, таких как iOS или Android, предоставляют достойную основу для начала. Это ставит разработчиков в рамки и дает рекомендации. Не так много в геймдеве, с большой гибкостью приходят кошмарные дизайнерские решения.

Часть проблемы заключается в том, что программирование пользовательского интерфейса сложно. В реальном мире нет простой аналогии, чтобы понять, как работает пользовательский интерфейс, а затем скопировать логику в программное обеспечение (как мы делаем с физическими движками или графическим программированием). Я всегда боялся вносить изменения в код пользовательского интерфейса. В конце концов, я решил понять, в чем заключаются проблемы с созданием надежного, легко читаемого и поддерживаемого кода пользовательского интерфейса. В течение прошлого года я работал над внутренней библиотекой пользовательского интерфейса и занимался программированием пользовательского интерфейса для предстоящего проекта, так что вот мои выводы.

  • Смешение различных шаблонов пользовательского интерфейса. Часто вижу, когда разные подходы совмещаются в одном проекте. MVC+MVVM+MVP и так далее. Это не комплементарные вещи, они должны заменять друг друга. Иногда шаблона нет вообще. Решение. Выберите одно из них и последовательно используйте его во всем проекте.
  • Непонимание того, как работает выбранный шаблон. Крайне важно четко понимать, каковы обязанности каждого компонента шаблона. Что делает View, ViewModel, Model, Controller, Presenter, Widget и так далее. Самое смешное, что на многих ресурсах в сети об одних и тех же компонентах пишут разные вещи. Решение. Для компании важно иметь единое представление о конкретном шаблоне. Ничего страшного, если он не полностью затронет все внешние источники, но чем ближе он к общеизвестным, тем проще будет привлечь новых разработчиков.
  • Утечка игровой логики в представления. Существует большое искушение изменить состояние игры прямо там, где обрабатываются нажатия кнопок, но изменение состояния игры из представлений — это скользкий путь. Это разрушает разделение интересов. И в случае, если что-то не так с состоянием игры, у вас будет меньше мест для поиска бага. Решение: общение с игрой и вызовы игровой логики должны передаваться только событиями/сообщениями. В зависимости от событий игровая логика должна изменить состояние игры.
  • Утечка логики просмотра в игру. Как и в предыдущем пункте, CharacterManager не должен изменять внутреннее состояние пользовательского интерфейса HealthBar. Решение: управление элементами пользовательского интерфейса должно выполняться представлением. Информация в View должна передаваться через ViewModel или события.
  • Отсутствие надлежащего WindowManager. Плохая идея обрабатывать создание окон или хранить ссылки на префабы пользовательского интерфейса внутри игровой логики/представлений. Решение: потратьте время на специализированный оконный менеджер, который может обрабатывать конфликты окон, накладывать друг на друга, сохранять ссылки на префабы и организовывать все, что связано с пользовательским интерфейсом.
  • Бонус: использование Rx (Reactive Extensions) в игровой логикеc. Rx — бесценный инструмент в программировании пользовательского интерфейса, но, пожалуйста, оставьте его в области пользовательского интерфейса. Решение: как правило, все структуры данных Subscribes to Rx должны происходить внутри View. Если вы начнете изменять состояние игры, подписываясь на Rx-события, вскоре вашу игровую логику будет трудно распутать.

Игры — это сложные проекты, и кодовая база мобильных игр часто на 50–80 % посвящена пользовательскому интерфейсу. Многие разработчики пытаются сократить код пользовательского интерфейса и быстро перейти к программированию геймплея. Но поверьте мне, потратив время на правильную архитектуру пользовательского интерфейса, вы получите больше счастья в долгосрочной перспективе.