Проектирование И Архитектура Игр
Posted : admin On 30.06.2019Nov 24, 2012 - Э. Моррис, Дэйв Моррис «Проектирование и архитектура игр» Издана. Из игр, скорее логические и простые 2d игры. Графические карты для игр на ПК, мобильных. ПРОЕКТИРОВАНИЕ И. Это первая архитектура.
- Проектирование И Архитектура Компьютерных Игр Fb2
- Проектирование И Архитектура Компьютерных Игр
- Проектирование И Архитектура Игр Pdf
Недавно команда Whistling Kite Framework выпустила в релиз очередную игру, на этот раз — Змейку, написанную на Unity3D. Как и в большинстве игровых проектов, при решении вопроса о том, насколько детально нужно проектировать приложение, критическим фактором было время.
В нашем случае причина проста: т.к. Разработка велась в свободное от основной работы время, то идеальный подход к проектированию отложил бы релиз ещё на год. Поэтому, составив первоначальное разделение на модули, мы закончили проектирование и приступили к разработке.
Под катом описание того, что из этого получилось, а также пара уроков, которые я вынес для себя. Осторожно, картинки! Сразу хочу вставить оговорку: все описанное ниже является лишь ретроспективой событий и попыткой анализа, что получилось хорошо, а что плохо. Статья не претендует на то, что в ней изложена непреложная истина, скорее даже наоборот — “вредные советы”, которые, возможно, уберегут кого-то от таких же ошибок.
Функциональность Вначале пара слов, собственно, о приложении, чтобы было понятно, что именно мы проектировали и разрабатывали. Создавая змейку, мы постарались воссоздать именно старую добрую классическую змейку, в которой не было ничего кроме змеи, яблок, стен и бесконечного желания двигаться дальше. Именно поэтому мы сосредоточились на классическом геймплее, заведомо исключив из него на данном этапе все дополнительные возможности. Одно из главных преимуществ нашей змейки — это разнообразные варианты управления, которые вы можете найти в настройках. Мы постарались предусмотреть их все:. 4 кнопки — задать новое направление движения;.
2 кнопки — поворот налево/направо от текущего направления;. свайпы — провести пальцем в нужном направлении. Планируем добавить еще два:. гироскоп — наклон устройства задает новое направление;. джойстик-”пузырь” — смещение пальца от первой точки касания задает новое направление. Набранный в партии рейтинг записывается в таблицу рекордов. Рекордом можно поделиться с друзьями через смс, почту или любую социальную сеть, подключенную на смартфоне — твиттер, вконтакте, фейсбук и т.п.
Решение о старте разработки змейки мы принимали, преследуя две цели:. Попробовав большую часть существующих под Андроид «змеек», мы не обнаружили такой, в которую хотелось поиграть нескольким участникам команды, мы решили исправить эту ситуацию;. Мы впервые решили выйти на мобильный рынок и использовать движок Unity3D, поэтому выбрали заведомо несложную игру, чтобы освоиться с ним.
Архитектура Этап 1. Концепция Первый, концептуальный, вариант архитектуры создавался нами ещё до выбора unity. Он приведен на картинке ниже.
В этом варианте мы выделили слои будущего приложения:. Слой инициализации;.
Слой интерфейса;. Слой логики;. Слой контроллеров;. Слой управления.
Исторически последним был выделен слой инициализации, хотя в приложении он должен был запускаться первым. Дело в том, что мы сначала заложили инициализацию объектов в сами объекты, но потом решили выделить ее централизованно. Слои интерфейса, логики и контроллеров представляют собой почти классической паттерн MVC. При этом было желание разделить обработку этих слоёв даже на разные потоки, чтобы обеспечить максимальную плавность интерфейса. Слой управления был вынесен отдельно, т.к.
Мы решили, что разнообразные варианты управления будут одной из наших основных фич, поэтому нужно было делать так, чтобы всё остальное приложение не зависело от выбранного варианта. Все слои должны были общаться между собой посредством выделенных интерфейсов, каждый слой содержал свои объекты и выполнял свои функции, зачастую содержал свой поток обработки. Хорошие идеи:. Выделение слоя инициализации: в последующих версиях это потеряли, что приводило иногда к довольно запутанным последовательностями действий. Правильная общая структура разделения приложения на модули: в дальнейшем границы различались и понятие инкапсуляции было практически забыто(можно привести картину «там баг» с котами, только заменить на «так нельзя! Как же инкапсуляция» Промахи:. Раздельные слои контроллеров и управления: впоследствии от контроллеров в терминах MVC отказались в силу избыточности.
Слишком высокоуровневое описание: непонятно, какой. Хотя это и нельзя назвать чистым промахом, т.к. На момент создания этой архитектуры не был выбран ещё движок. Следующим этапом стал выбор платформы, хотя, строго говоря, выбор делался между unity и разработкой на чистой java. Беглый обзор других существующих движков не вызвал энтузиазма в их изучении. Мы пришли к достаточно ожидаемому выводу: написать змейку проще вообще без платформы, к тому же это выглядело интереснее — кто ж не любит делать свои велосипеды?
Однако, мы выбрали unity, с целью ознакомления с платформой, близкой к статусу стандарта де-факто в области гейм-дева. Да, мы получили солидный оверхед из-за того, что unity — трёхмерный движок (на момент начала разработки у unity еще не было нативной поддержки 2D), а делали мы двумерную игру, но полученный опыт того стоил. Проект Пока выбирали платформу, мы совместными усилиями писали дизайн-документ, и уже на его основе родился второй проект архитектуры, заточенный под выбранную платформу. Эта архитектура состояла из нескольких связанных диаграмм, которые я ниже называю терминами uml, хотя, конечно, стандарту они следуют, мягко говоря, не полностью. Сущность-связь (понятно, что это скорее относится к разряду требований к системе, чем к её архитектуре, но в контексте статьи я не могу её не упомянуть: Нотация ERD, думаю, всем знакома. На ней представлены все объекты игровой логики и логические связи между ними. Каждый такой объект порождает один класс, обеспечивающий работу этого объекта.
Диаграммы компонентов и кооперации. Для их восприятия предварительно опишу ряд договоренностей: Общая архитектура — носит общий концептуальный характер, являясь, по сути, продолжением диаграммы этапа 1. На ней отображены:. Компоненты системы (прямоугольники);. Подсистема хранения (символ БД, магнитного диска);.
Примечания (желтые “листки”);. Потоки управления (закрашенные стрелки);. Потоки данных (пунктирные стрелки). Детализирующие диаграммы содержат:. Компоненты, объекты (прямоугольники);. События, обрабатываемые объектами (шестиугольники);.
Действия, выполняемые по событиям (эллипсы). В целом концепция изменилась не сильно: также есть отдельный компонент для инициализации, далее выделены две основные подсистемы. После запуска приложения первым начинает работать компонент инициализации: он запрашивает у хранилища все необходимые данные и инициирует подсистему GUI. Подсистема GUI должна обеспечивать работу пользователя с главным меню, настройками и рекордами. При старте игры, контроль передаётся на подсистему управления. Подсистема управления должна обеспечивать взаимодействие пользователя с игровым миром, в первую очередь это — управление непосредственно змейкой. Отдельно выделены компоненты для логирования и расшаривания рекордов.
Игровой мир состоит из объектов, взятых с ERD. Ключевую роль играют партия и змейка. Партия хранит ссылки на змейку и текущий экземпляр фрукта, обеспечивает инициализацию игровых объектов и их взаимодействие. Змейка обрабатывает основные игровые события: собственное движение, поедание фрукта и столкновения со стенами или хвостом. Экземпляр фрукта отвечает за контроль собственного времени жизни.
Хорошие идеи:. Выделение двух основных независимых подсистем: при разработке это не было учтено, что первоначально привело к большому количеству лишних сцен. Промахи:. Не учитывает разделение по сценам и работу с подсистемой хранения из игровой сцены. Не отвечает на вопрос, как реализовывать подсистему GUI и как подсистемы взаимодействуют между собой. Объект Партия взял на себя функции контроллера в терминах MVC. Фактический результат После старта разработки архитектуру уже никто не корректировал.
Я только оставлял отдельные заметки в соответствующем разделе дизайн-документа о том, как реализованы те или иные узкие места, но основная цель была выпустить релиз. Что ж, этой цели мы достигли, и я сел за рефакторинг, чтобы подготовиться к разработке второго релиза. Уже на тот момент я понимал, что в первую очередь надо переводить игру на честный 2d, поддержка которого как раз появилась в unity. И ещё было понимание, что полученный результат далёк от идеального, в первую очередь в части разделения функций по объектам и их взаимодействию, поэтому, я поставил себе две задачи:. Составить общую диаграмму классов. Составить диаграммы последовательности для основных сценариев приложения.
На основе этой информации я планировал получить список того, что нужно менять. Результаты такого реверс-инжиниринга представлены ниже, в каждом разделе я сначала кратко описываю, о чем этот раздел, потом привожу одну или несколько диаграмм, иллюстрирующих построенное решение, а потом детально описываю, что и как было сделано.
Обзор созданных классов На диаграмме ниже представлены все классы, созданные при разработке игры. На диаграмме скрыта часть методов, не несущих смысловой нагрузки или настолько тривиальных, что не стоят упоминания. Также часто под именем переменной (например, textures) скрывается целый блок переменных (в данном случае — разнообразных текстур). Все имеющиеся классы разделены по четырем пакетам:.
Gamelogic — здесь представлены классы для игровых объектов, существующих на ирговом поле. По сути, этот паявляется ядром игры. Gui — здесь представлены классы, отвечающие за построение статического пользовательского интерфейса: главное меню, настройки, рекорды и кнопки поверх игрового поля, кроме кнопок непосредственного управления змейкой.
Controllers — это изюминка нашего приложения: пакет с разнообразными способами управления змейкой. Каждый класс полностью содержит в себе все необходимое для выбранного стиля управления: от интерфейсных кнопок до логики расчета поворота.
Providers — этот пакет содержит вспомогательные классы, обеспечивающие такие функции, как чтение и сохранение данных, возможности поделиться рекордом, логирование, аналитику и т.п. В пакете игровой логики центральное место занимает класс party, представляющий собой одну игровую партию. Этот класс отвечает за начало и окончание игры, за начисление рейтинга, за координацию событий поедания яблока и истечения времени жизни яблока и много других вспомогательных функций.
Пока писалась эта статья, я практически переписал этот класс, оставив в нем только вызовы методов из других классов (собственно, змейки и яблока). Это больше соответствует требованиям инкапсуляции, но сделало этот класс еще более похожим на контроллер в терминах MVC. Второй по важности класс Snake содержит логику движения змеи, включая управление зависимыми объектами класса Snakechain. Именно этому классу передают команды контроллеры управления.
Для создания экземпляров фруктов (FruitInstance) используется фабрика, т.к. В будущем планируется увеличивать количество разных типов фруктов. Пакет с интерфейсами содержит отдельные классы, отвечающие за отображение и обработку пользовательского интерфейса в зависимости от ситуации. Там же обрабатываются нажатия железных кнопок на устройстве.
Пакет с контроллерами содержит управляющие классы. Они добавляются к змейке и взаимодействуют напрямую с объектом Snake, используя паттерн command, а змейка выполняет поступившие команды в той же последовательности, но раздельно по своим шагам. Это было сделано для корректной обработки быстрых последовательных команд, например для разворота на 180 градусов вдоль своего хвоста.
Пакет с провайдерами содержит только один класс, интересный для данной статьи — это dataProvider. Этот класс содержит набор статичных функций, являющихся оберткой над вызовами стандартных методов для работы с хранимыми свойствами. На обоих предыдущих этапах проектирования работа с сохраненными данными предполагалась только однократно: загрузить их в память и больше не обращаться к более медленным носителям. Такой подход не учитывал вопрос независимости сцен в Unity: в результате, при переходе между сценами главного меню и игрового поля, все необходимые данные приходилось перечитывать заново. Начальные состояния Ниже приведено описание начального состояния двух сцен, из которых и состоит игры: сцены главного меню (на рисунке ниже слева) и сцены игрового поля (на рисунке ниже справа).
Начальное состояние определяется тем, что было введено в редакторе, до запуска любого исполняемого кода. Именно из этих состояний начинаются большинство диаграмм последовательности ниже. Главное меню создается двумя классами, Player и GUInavigator, присоединенными к единственному объекту на сцене, к камере. Player отвечает за загрузку всей основной информации об игроке, а GUInavigator инициирует нужное поведение из пакета интерфейсов и обеспечивает дальнейшие переходы между интерфейсами. Игровая сцена содержит гораздо больше объектов.
Проектирование И Архитектура Компьютерных Игр Fb2
Большинство из них статические, представляющие собой мир змейки: фон, игровое поле, стены. Дополнительные поведения прикрепляются только к двумя объектам: к камере (GUInavigator, Player, party, fruitfabric) и голове змейки (Snake, Controllerselector).
Controllerselector отвечает за выбор управляющего контроллера в соответствии с настройками игрока. Запуск приложения Диаграмма ниже отражает процедуру старта приложения (в той ее части, которая контролируется разработчиком). Особое внимание можно уделить разве что альтернативному выходу из сценария и переходу к загрузке игры, если есть сохраненная незавершенная партия. Загрузка приложения состоит из обработки двух событий: awake и start. Событие awake обрабатывает объект player: в этот момент он обращается к DataProvider-у для загрузки информации об игроке, а потом вызывает собственный метод, отвечающий за применение текущих настроек, например, отключение звука. Событие Start обрабатывается чуть посложнее:. GUInavigator в методе initMain инициирует все необходимые в данной сцене интерфейсы, каждому проставляя признак неактивности.
Далее он проверяет, не было ли сохранено незавершенной игры. Это возможно, например, при прерывании игры входящим звонком. Если игра есть, то происходит загрузка игровой сцены, а данный сценарий прерывается. Условно одновременно с этим обрабатываются события Start для всех инициированных классов интерфейсов — в них происходит дополнительная инициализация, свойственная каждому конкретному интерфейсу в отдельности (в т.ч. Интерфейс рекордов загружает данные по таблице рекордов, используя dataProvider). Интерфейсу главного меню присваивается признак активного, и он отображается пользователю.
Запуск игры Далее рассмотрим диаграмму последовательности, иллюстрирующую действия при запуске игры. Точка начала — загрузка сцены с игрой. На данной диаграмме стоит отдельно отметить альтернативный сценарий загрузки сохраненной игры — это нужно для случая прерывания игры, например, входящим звонком.
Первыми срабатывают события Awake для объектов Player (загрузка всех настроек, аналогично старту приложения) и Snake (метод Init — инициализиция хвоста “по умолчанию” из двух сегментов). Потом срабатывает событие Start для выбора контроллера (для примера использован FourButtonController), загрузки GUI и инициализации игры.
Чуть подробнее об обработке этого события:. Controller selector в событии Start, проверяет настройки игрока и подгружает нужный контроллер управления. GUInavigator в методе initGame инициирует все необходимые в данной сцене интерфейсы, каждому проставляя признак неактивности. Определение, какой метод вызвать, прроисходит на основе параметра, заданного через редактор. Инициализация и включение активного интерфейса происходят аналогично запуску приложения. Далее событие Start обрабатывает объект party.
Первым делом он проверяет, нет ли сохраненной игры. Если игра есть, то party вызывает dataProvider для восстановления, который, прочитав данные вызывает метод Restorebackup объекта party. Он, в свою очередь вызывает аналогичный метод объекта Snake, а тот по цепочке для всех звеньев. После восстановления данных, управление возвращается объекту party, он включает паузу и ждет действий игрока. Если же игры не было, то party вызывает фабрику фруктов для создания экземпляра и игра началась. Кстати, на диаграмме показано, что party отвечает и за установку ряда параметров для фрукта — сейчас это уже не так: все необходимые действия инкапсулированы либо в фабрику, либо в экземпляр фрукта.
Игровой цикл: движение змеи Игровая логика сосредоточена вокруг обработки двух событий: update обрабатывается в змейке методом movehead, здесь происходит движение змеи и управление движением ее сегментов; и ontriggerenter, где происходит обработка столкновений головы змеи с фруктами, стенами и собственным хвостом. Разберем событие столкновения подробнее:.
При возникновении события сначала проверяется, с кем мы столкнулись: если это яблоко, то вызывается метод Eatfruit, а если хвост или стена, то Killme. В обоих случаях информация о столкновении сбрасывается в логи. Случай яблока:. Змейка выставляет флаг необходимости добавления звена и вызывает метод Eatfruit объекта party. Party увеличивает рейтинг партии и вызывает свой же метод createfruit, использованный также при запуске игры. В этом методе сначала удаляется текущий экземпляр фрукта, а затем создается новый через обращение к фабрике. Случай стены или хвоста:.
Змейка передает обработку события объекту party в метод Endgame. Party выставляет режим паузы и, через навигатор интерфейса, переводит игрока на экран с результатами партии. Движение же змейки реализовано следующим образом:. В событии update вызывается метод movehead. Здесь проверяется скорость змейки: наступил момент перехода или нет. Если да, то проверяется флаг необходимости добавления звена.
Если нужно, то создается звено, аналогичное следующему за головой. Смещаются только голова и одно вновь созданное звено. Если флага нет, то смещается голова, а за ней по цепочке все звенья, методом adjust. Заключение За рамки данной статьи осталось достаточно много логики: это логирование, как внутреннее, так и с использованием внешних средств аналитики; это работа навигатора интерфейсов, который инкапсулирует все особенности, связанные с двумя сценами; это работа с данными, с устройством, показ рекламы и еще много других особенностей. Если кому-то будет интересно, я могу написать об этом отдельно.
Основные выявленные проблемы:. Замена 3d на 2d. Из диаграмм это не следует, но очевидно с точки зрения предпочтительности использования инструментов по их назначению. Объект party слишком перегружен функциями: он управляет и яблоками, и змейкой, и обработкой завершения игры. Перегружен игровой интерфейс — его надо разделять на два состояния: в игре и после столкновения.
Отсутствует фасад для работы с функциями устройства, не предусмотренными движком: в нашем случае для андроида это переопределенный метод вибрации, реализация кнопки share (вызов системного окна для выбора приложения) и реализация вызовов гугл- аналитики. Какие выводы для будущих проектов я сделал, исходя из всего вышесказанного?. Надо знать платформу, прежде чем браться за что-то серьезное.
Это в общем -то очевидно, но на всякий случай решил это повторить, может кого-то убережет от запуска очередного убийцы топ ММО без опыта. Необходимо проектировать разделение приложения (даже простого) на компоненты. На этом этапе главное — минимизировать количество взаимодействий и потоков данных. Продумывая структуру классов, нужно сразу продумывать, как объекты будут соотносится с компонентами и какие функции (группы функций) будут они выполнять.
С одной стороны, нужно поддерживать связь с запланированной архитектурой, но с другой стороны, нужно быть готовым ее изменять, при возникновении новых условий. Если вы видите еще какие-то не оптимальные решения, то прошу высказываться в комментариях, с удовольствием обсудим. На всякий случай в конце привожу все ссылки, релевантные к статье:. Диаграмма архитектуры этапа 1 нарисована. Диаграммы архитектуры этапа 2 нарисованы на andoroid-планшете в приложении;.
Диаграммы архитектуры этапа 3 нарисованы в;. Обсуждаемое приложение можно посмотреть. Узнать больше о нашей команде можно на нашем.
За время подготовки данной статьи, часть найденных ошибок уже была исправлена, и, вероятно, были внесены новые, т.к. Разработка не стоит на месте. Метки:. Добавить метки Пометьте публикацию своими метками Метки необходимо разделять запятой. Например: php, javascript, андронный коллайдер, задача трех тел. Критик из меня так себе, но я попробую перечислить моменты, которые бросились в глаза:. Текстуры заметно тайлятся.
Трава на фоне и на поле, где ползает змейка, идёт очень заметными повторяющимися кусками. Не лучше ли было использовать одну текстуру без повторений? Или вот, например, на фоновой картинке таблицы рекордов тоже стоит тайлящаяся картинка, но за счет изменений цветности и «выбеленности» некоторых участков ощущение повторяемости уже не такое сильное. Я понимаю, что вы старались придерживаться мультяшной стилистики, но всё же текстуры можно сделать на основе фотографий, их много на cgtextures, в резделе nature/grass. Границы сред никак не обозначены.
На стыках фоновой травы и камней можно сделать небольшое затенение, чтобы визуально улучшить разделение этих объектов. У вас так сделано на границах досок. А вот на траве поля его нет, — и сразу кажется, это ковер, расстеленный на камнях.
Одинаковых, кстати. Элементы управления сливаются с окружением.
Тот же эффект тени, отбрасываемой ими на картинку игры, и выделение их другим цветом создадут впечатление того, что они не имеют отношения к миру игры, как камни, например. Я бы порекомендовал больше использовать эффекты полупрозрачности.
Плавные переходы наше всё:). Слишком много «рамочек».
Полосатый фон, потом белая рамка, потом фон травы, потом окаймление из камней. Впрочем, это дело вкуса. Прошу не принимать мои предложения как критику. Статья все же о пайплайне разработки, а не о графике.
Статья хорошая, но очень уж сложная. Мне кажется, в конце можно было бы выделить ключевые моменты проектирования игры на Unity в разрезе особенностей работы с объектами этого же Unity (у вас получилось очень обобщенно). Я тоже начинающий Unity-разработчик и уже успел ощутить, насколько там сложно разделить код на модули. Мы с коллегой-художником тоже решили начать с простых 2D игр для Android, 2 из которых в итоге, как и вы, успешно опубликовали в Google Play.
В первом проекте в скриптах творился полный хаос. Второй я начал писать более осмысленно, старался как можно больше инкапсулировать, но все равно связей осталось много, и какие-то выводы сделать достаточно сложно. Заметил, что учитывая простоту, вы все равно решили разбить по сценам. Я же, после первого проекта, наоборот решил, что одной сцены вполне хватит (что позволило, к слову, сделать плавные выезжающие менюшки). Если бы у меня были простые рецепты, я бы их написал, но, к сожалению, это не так. Предлагаю вместе двигаться в сторону открытия этих рецептов. Я вижу преимущество в разделении сцен в том, что независимые компоненты максимально разделены, в т.ч., при добавлении различных новых режимов игры (например, кампании), я буду только расширять состав сцен и модифицировать интерфейс меню.
Основная же логика останется в неприкосновенности, это должно минимизировать вероятность внесения новых ошибок в отлаженную функциональность. А выплывающие меню можно сделать путем переиспользования классов, отвечающих за построение меню, например, в моем случае это можно сделать так:. Взять код, отвечающий за построение интерфейса меню (содержимое метода OnGUI) и выделить его в отдельный класс.
Изменить класс MainGUI (или SettingsGUI — в зависимости от того, какое именно меню хотим выделить), убрав из него отрисовку меню, но пронаследовав от нового созданного класса. Пронаследовать GameGUI от нового класса и добавить вызов отрисовки меню + анимацию выезжания Собственно, я бы сделал именно так, независимо от того, была бы у меня одна сцена или несколько. Но в любом случае, я инкапсулировал всю логику, связанную со сценами, в один класс GUINavigator, так что в моем случае замена на одну сцену — дело 15 минут, если возникнет такая необходимость. Много, однако, в вашем сообщении аббревиатур GUI. А я вот в процессе изучения матчасти не раз встречал плохие отзывы об этом компоненте движка. Якобы метод OnGUI слишком тяжеловесный, создает дополнительные DrawCalls, что негативно сказывается на производительности, в особенности на мобильных устройствах. Хотя, поиграв в вашу Змейку, могу сказать, что работает все очень гладко и быстро, видимо продуманная архитектура дает плоды:) И все таки из-за загрузки новой сцены вы не сделаете красивые переходы.
Это ведь как одностраничный и многостраничный сайт. Ну это так, на вкус и цвет. Мне просто понравились мои переходы (можете ) Еще немножко оценю вашу игру, если вы не против.
Текст на кнопках очень мелкий, вы не отталкиваетесь от размера экрана при их инициализации? Рекламу сделали, а вот онлайн таблицу рекордов нет. Посчитали ненужным или не захотели перегружать игру излишним функционалом?
И все таки из-за загрузки новой сцены вы не сделаете красивые переходы. Не будьте так категоричны. В своей первой игре (Fondemzel Labyrinth) я использовал плавные переходы между сценами таким образом: перед выгрузкой сцены экран затеняется в ноль, а при загрузке другой — постепенно высветляется до нормального состояния из кромешной черноты.
Думаю, таких примеров можно привести множество. Использование нескольких сцен — одна из возможностей распределения игровых ресурсов и их сортировки, причем очень мощная и удобная. Вы правы в том, что к разработке OnGUI необходимо подходить очень тщательно, чтобы не было проблем с производительностью. Об этом пишут в т.ч. Сами разработчики Unity, и уже вышла бета-версия с новым механизмом UI, который должен заменить устаревший OnGUI.
Вы, кстати, ее уже попробовали? На чем делали свой интерфейс?
Проектирование И Архитектура Компьютерных Игр
Однако, вы ошибаетесь в том, что раздельные сцены не позволят сделать красивые переходы: это вещи совершенно не связанные. Возможно, раздельные сцены не позволят сделать переходы так, как они сделаны у вас, но это совсем другая формулировка, верно? Разделение на сцены объективно имеет как преимущества, так и недостатки. Но субъективную оценку красоты предлагаю оставить игрокам, все-таки, это им должно нравится приложение, а не нам с вами. Вам правда интересно про таблицу рекордов?
Просто в вашей фразе Посчитали ненужным или не захотели перегружать игру излишним функционалом? Оба варианта суть одно и то же. Обычно так говорят, когда для себя уже все решили, что печально. Если все же интересно, то онлайн таблицу рекордов мы планируем сделать одновременно с дополнительным режимом игры — прохождением кампании.
Конкретно мне интересно послушать про организацию способностей, что они из себя представляют, как реализованы на уровне исходного кода. Если играли, то наверняка замечали, что их там великое множество, довольно четко прописаны правила их взаимодействия, все прямо скажем непросто. Это «что именно». Но и в целом про основной цикл, распределение ролей по клиенту и серверу и т.д. Не нужно воспринимать мой довольно резкий вопрос как большинство (минусами в карму), просто не хотел тратить время на пояснения, а в ответ ничего не услышать.
«машины состояний» (state machines) — это то, что в общепринятой русскоязычной терминологии называется конечными автоматами Использование кальки «машина состояний» позволяет избежать смешения с математической абстракцией «конечный автомат». Программистская машина состояний принадлежит к другому классу мощности, нежели математический конечный автомат. В частности, допускает «бесконечное» множество состояний (параметризация состояний), бесконечный алфавит (параметризация событий), наличие состояний у состояний (sic!), зависимость переходов не только от явного входа и текущего состояния, но и от состояния «мира».
Спасибо за ссылку на книгу! Надо будет глянуть, в том числе и другие ее части. Правильнее было бы сказать, что я не встретил книги или публикации, где собраны воедино описания реализаций типовых игровых механик, таких как: характеристики объектов; баффы/дебаффы; способности/заклинания; организация процессов экипировки персонажа, изучения навыков, покупки, особенно в клиент-серверных играх; система диалогов; система квестов. Пока что пролистал мельком книгу.
Про КОП, FSM, Behavior Tree в ней написано. А вот про перечисленное выше я не увидел. Большинство книг по архитектуре игр обычно ориентированно скорее на создание архитектуры движка, чем самой игры. КОП как бы более продвинутое ООП. Коп — это уровень сборки приложения, когда у компонента есть не только код, но и данные и ui.Тут просто одно и то же название используется в разных контекстах. То, о чем вы говорите – скорее модулями правильней называть, а не компонентами. Для кругозора можно еще почитать про аспекты (ваши компоненты на них сильно похожи) и мультиагентное программирование.Полезно конечно будет почитать.
Но из того, что я сейчас прочитал про аспекты – не сказал бы, что мои компоненты на них похожи. Я так понял, что если какой-то общий функционал вынести в отдельный метод, и как-то организовать его вызов при выполнении любого метода в любом классе, к которому он привязан, то эта дополнительная привязанная функциональность и будет называться аспектом. КОП не продвинутое ООП, а надстройка над ним. Согласен с вами по сути изложенного, но не согласен по форме: нельзя противопоставлять ООП и КОП, иначе, прочитав вашу статью, может сложиться впечатление, что ООП — устаревшее зло без права на всплытие. В вашем примере, кстати, компоненты, отвечающие за урон ближнего боя и урон дальнего боя, вполне логично пронаследовать от одного компонента, отвечающего за урон в принципе. Согласен, что не нужно пытаться использовать ООП для объектов игрового мира, т.к. Они заведомо собираются из различных компонент (начиная от transform и rigitbody, заканчивая контроллерами баффов и собственных действий), но его можно и нужно использовать для реализации аспектов, действительно связанных отношениями родитель-потомок.
Статья не идеальная, что тут сказать. Тема компонентного подхода плоховато раскрыта. На мой взгляд, выделение компонентов похоже на выделение интерфейсов. Но компоненты помимо описания позволяют еще и реализацию вынести в отдельный класс. В одних случаях стоит базовый класс использовать, в других – интерфейс. Аналогично и с компонентами. Ну и вдобавок, в некоторых случаях для компонентов стоит также выделить интерфейс.
В вашем примере, кстати, компоненты, отвечающие за урон ближнего боя и урон дальнего боя, вполне логично пронаследовать от одного компонента, отвечающего за урон в принципе.Согласен. Да и упоминал немного в статье, что наследование компонентов – вполне нормально. Вот и мне непонятно. Не скажете, где говорится, что медиатор или что-то подобное плохо в коп? Мне таким образом стало куда удобней работать, чем в каждом компоненте заводить несколько ссылок на другие компоненты и вызывать getComponent для получения каждого. Компоненты какого-то сложного объекта в любом случае как-то должны общаться друг с другом.
Проектирование И Архитектура Игр Pdf
Поэтому не вижу проблемы добавления класса-посредника для конкретного типа объекта. В случае посредников для объектов сцены, особенно если их разделять по подсистемам (гуи, звук), тоже не вижу проблем. Объектам сцены все равно как-то потребуется обращаться друг к другу. Касательно Unity3d. В нем раньше было сделано так, что у компонента были ссылки на кучу других компонентов, которые он не использует, что приводит к ненужной связанности компонентов. И это скорее создавало проблемы разработчикам движка, а не разработчикам, которые пишут на движке.