Записки велосипедиста #2 - Внутренности игровых движков

Добавлен , опубликован

Записки велосипедиста #2 - Внутренности игровых движков

Здравствуй, %username%!
Этот ресурс - продолжение цикла познавательных "Записок велосипедиста", в котором я рассказываю про свои "приключения" и даю ссылки на интересные материалы для домашнего изучения.

Дисклеймер

Если Ваши grammar Nazi's чувства не позволяют вам наблюдать жаргонизмы и некоторые случайные орфографические или пунктуационные ошибки - немедленно крикните три раза "Ко-ко-ко", позвоните по номеру 03, сообщите своё текущее местонахождение и объясните прибывшим специалистам суть Вашей проблемы.

Вступление

Доброго времени суток!
Сегодняшний номер, как я и обещал, будет более практикоориентирован.
Кода не будет, так как нефиг, рано ещё код смотреть! Батя в вашем возрасте кушал кислоту и тыкал иглой в перфокарты, а о коде мог только мечтать! Так что нефиг, рано ещё!
Сегодня мы поговорим о программных внутренностях игровых движков. Итак, приступим.

На кой мне сдался ты, товарищ?

Собственно. Игровой движок - инструмент, который облегчает процесс создания в первую очередь технической части игр.
Из чего состоит эта техническая часть? Мы можем понять это исходя из того, что умеет любая игра:
  1. Узнавать о том что игрок нажал клавишу на клавиатуре, кликнул кнопку на мышке или использовал любой другой источник ввода.
  1. Обрабатывать эту информацию, переводя непонятные для игры события, в понятные. Например: игра не понимает что значит "Ctr + 1", но обработав это сочетания в соответствии с контекстом мы можем получить то, что понимает игра: "Выбрать войска на карте, принадлежащие к группе 1".
  1. Исполнять действия, связанные с этим событием. Например, в соответствии с предыдущим событием, игра убирает текущее выделение, получает все войска, входящие в группу 1, каждого выделяет и переносит фокус камеры на одного из них.
  1. Исполнять всякие другие действия, предусмотренные замыслом игры. Например менять день на ночь или обрабатывать столкновения объектов в игровом мире.
  1. Уведомлять игрока о событиях, произошедших в игровом мире. Это рендеринг (прорисовка) мира на экран монитора, звуки из колонок, вибрация на геймпаде и прочее, из чего игрок получает информацию от игры.
Именно постоянное чтение ввода и вывод делают игру интерактивной.
И с каждым из пунктов, игровой движок может оказать вам неоценимую помощь, взяв на себя большую часть, а то и полностью автоматизировав и унифицировав то, что лежит в основе этих пунктов, предоставляя вам каркас, который содержит всё, для того, чтобы сделать процесс разработки игры легче!

И что это за магия?

Для выполнения своей миссии, игровые движки организуют в той или иной мере обособленные системы, из которых очень часто можно выделить следующий список:
  1. Контроллер игрового процесса (ядро) - организует работу пользователя с движком, определяет ход выполнения игровой программы, управляет работой других систем.
  2. Система событий - используется другими системами движка для общения между собой.
  3. Система отладки, профилирования и обработки ошибок - записывает системные события, ошибки и осуществляет мониторинг памяти и прочих ресурсов, используемых движком.
  4. Система ввода - получает события от устройств ввода, обрабатывает и передаёт их в систему событий.
  5. Система ассетов - управляет загрузкой и выгрузкой в память любых ресурсов. Облегчает работу с этими ресурсами.
  6. Менеджер сцены - управляет сценами и игровыми объектами/сущностями на этих сценах.
  7. Физический движок - симулирует физические явления игрового мира, управляя игровыми объектами.
  8. Система анимаций - позволяет анимировать модели, текстуры и в идеале что угодно.
  9. Звуковой движок - позволяет воспроизводить любые виды музыки и звуковых эффектов, симулирует физические явления, связанные со звуком в игровом мире.
  10. Визуализатор - превращает сцену, на которую он смотрит с определённого ракурса, в картинку, которая затем, например, попадает на экран монитора.
  11. Сетевой движок - позволяет использовать сетевые подключения для создания многопользовательских игр.
  12. Скриптовый движок - интерпретирует маленькие DSL-программы (скрипты) и применяет описанную в них логику в контексте игры.
  13. Система игрового ИИ - облегчает работу с игровым ИИ.
Это очень сжатое описание основных подсистем движка. Каждая из этих систем, в свою очередь может состоять из множества других. Некоторые из систем работают каждую итерацию игрового цикла (тик) (физический движок к примеру), некоторые - работают при смене сцены или других событиях (например система ассетов).
Кроме того отдельно можно выделить утилиты, являющиеся в некотором роде библиотеками. Их назначение - облегчить некоторые операции, но в отличии от систем движка, утилиты можно не использовать вообще. Например: класс, содержащий методы, упрощающий какие-то вычисления. Движок может его не использовать, а разработчик в свою очередь может им воспользоваться.

Многабукаф, но я осилил. Что дальше?

Я тоже. А дальше...
Дальше только ещё больше букаф. А вы что предполагали?
Теперь мы плавно подъехали к вопросу: как же эти системы взаимодействуют между собой в игре?
На этот простой вопрос, у каждого движка может быть свой ответ.
Однако в целом, мы можем заметить сходства каждого движка. Они заключаются в порядке исполнения итоговой игровой программы (и на этом очень часто заканчиваются):
  • Игрок запускает игру
  • Из кода игры (или сразу) запускается ядро, которое сразу же инициализирует системы движка
  • Управление возвращается в код игры для инициализации систем самой игры
  • Ядро заканчивает инициализацию систем и запускает игровой цикл
  • Каждый тик:
    • Система ввода получает события ввода от устройств ввода, а также обновления состояния от сетевого движка.
    • Управление возвращается в код игры и в скриптовый движок для выполнения необходимых операций
    • Движок передаёт управление физическому движку, системе анимаций и прочему вычисляющему сброду
    • На основе нового состояния, движок при помощи звукового движка и визуализатора, выдаёт результат работы игроку
  • После того как игровой цикл был остановлен, управление передаётся коду игры для того, чтобы игра могла остановить свои системы
  • Затем происходит остановка систем движка и возвращение в код игры (где уже завершается программа)
Это простейший алгоритм работы клиентской версии игры. Для серверной версии нет необходимости выводить что-либо на экран. Только получать от программ-клиентов данные, обрабатывать и отсылать им своё состояние.

Вроде не сложно...

Именно. В этом нет ничего сверхсложного.
И теперь, когда мы поняли как устроены типичные игровые движки в целом, можно приступать к их детальному разбору.
Должен предупредить, что в последующих номерах вы столкнётесь с программным кодом, написанным на Java, поэтому я настоятельно рекомендую заранее получить базовое представление об этом языке и принципах его работы.

Линк тайм

По Java ресурсов полно в интернете, что аж блюёт, но рекомендую: Теперь по теме: Если есть дополнения - предлагайте :)
В каждом номере мы будем анализировать существующие подходы и делать то, что уже сделано, но как можно лучше.
Если Вам интересна данная тема - не стесняйтесь и жмите "Мне нравится" :3
Я долго думал насчёт того о чём писать следующий номер и понял, что лучше будет спросить об этом у вас, дорогие друзья!
Опрос: О чём делать следующий номер?
1. 
Подробнее об игровом цикле и взаимодействии компонентов (на примерах)
2. 
Об известных компонентах, используемых во многих игровых движках (Bullet, OpenGL/Direct3D, FMOD, Havok, PhysX и иже с ними)
3. 
Об истории игровых движков (это вообще кому-нибудь интересно?)
4. 
Обо всех перечисленных системах в отдельности
5. 
Написал в комментариях
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
0
24
8 лет назад
0
Не упомянуты такие вещи, как Entity System (хотя далеко не все ими пользуются, конечно - сложная штука), многопоточность, система работы с шейдерами (странно видеть отдельно сетевую систему, систему анимаций и систему загрузки ассетов, но не видеть отдельную систему для работы с шейдерами). Кроме того, универсальная система событий далеко не всегда есть в наличии "из коробки", например готовая реализация может использоваться только для обработки пользовательского ввода, а дальше уже как хочешь, так и выкручивайся. Сетевая компонента тоже часто представлена не полноценным движком, а на уровне вспомогательной библиотеки. Также ни слова не сказано про специальные форматы для ассетов, которыми грешат практически все движки.
Вроде все, что с первого раза на глаза попалось, завтра перечитаю еще раз.
2
29
8 лет назад
2
как Entity System
У меня как у задрота веб разработки, это вызывает ассоциацию с базами данных. В данном контексте это что?
prog:
многопоточность
Многопоточность штука сложная сама по себе, что уж там говорить про игры. Достаточно трудно выделить части, которые можно общитывать параллельно. Но это не значит, что не возможно.
prog:
система работы с шейдерами (странно видеть отдельно сетевую систему, систему анимаций и систему загрузки ассетов, но не видеть отдельную систему для работы с шейдерами)
Сперва подумал, что что тут странного, но раз система анимаций вынесена. То вопрос действительно остается открытым.
ZLOI_DED:
Очень интересно узнать про реализацию сетевого движка.
0
24
8 лет назад
0
У меня как у задрота веб разработки, это вызывает ассоциацию с базами данных. В данном контексте это что?
Многопоточность штука сложная сама по себе, что уж там говорить про игры. Достаточно трудно выделить части, которые можно общитывать параллельно. Но это не значит, что не возможно.
В общем случае, в отдельные потоки уходят: рендеринг (та его часть, что выполняется на CPU, в основном это подготовка сцены к передаче на GPU), физика, аудио и часто загрузка ассетов. Ну и сверху добавляются различные специфичные вещи, зависящие уже от конкретной игры.
0
29
8 лет назад
0
prog, ну вообще да, кст, асинхронная загрузка ассетов, штука полезная.
0
10
8 лет назад
Отредактирован ZLOI_DED
0
prog:
Не упомянуты такие вещи, как Entity System (хотя далеко не все ими пользуются, конечно - сложная штука), многопоточность, система работы с шейдерами (странно видеть отдельно сетевую систему, систему анимаций и систему загрузки ассетов, но не видеть отдельную систему для работы с шейдерами). Кроме того, универсальная система событий далеко не всегда есть в наличии "из коробки", например готовая реализация может использоваться только для обработки пользовательского ввода, а дальше уже как хочешь, так и выкручивайся. Сетевая компонента тоже часто представлена не полноценным движком, а на уровне вспомогательной библиотеки. Также ни слова не сказано про специальные форматы для ассетов, которыми грешат практически все движки.
Вроде все, что с первого раза на глаза попалось, завтра перечитаю еще раз.
Entity System - я подразумевал как часть менеджера сцены. Отдельно обычно не существует.
Многопоточность - относится к устройству контроллера игрового процесса (ядру). Отдельно выделить нельзя.
Система работы с шейдерами - это часть визуализатора.
Про систему событий и сетевой движок... я специально сказал что данный список можно выделить очень часто. Т.е. не все так делают, но большинство.
Про спец. форматы - это обзорный номер. Не знаю почему они ими "грешат", но это так или иначе часть системы ассетов.
Благодарю)
alexprey:
система работы с шейдерами (странно видеть отдельно сетевую систему, систему анимаций и систему загрузки ассетов, но не видеть отдельную систему для работы с шейдерами)
Сперва подумал, что что тут странного, но раз система анимаций вынесена. То вопрос действительно остается открытым.
ZLOI_DED:
Очень интересно узнать про реализацию сетевого движка.
Система анимаций вынесена отдельно, т.к. она занимается не связанной с физ. движком деятельностью.
А вот шейдеры привязаны к визуализатору и поэтому выделить их в отдельную систему не получается.
Хорошо. А что интересно? Как взаимодействуют клиент и сервер, какие протоколы используются, в чём их преимущества или всё сразу?)
Спасибо за фидбек!)
P.S. На самом деле здесь разделение систем даже более теоритическое чем то, какое бы вы делали в действительности. Т.к. смысла например, выносить систему событий из ядра, нет, но по сути это отдельная система, отдельный топик о котором можно говорить. :)
0
24
8 лет назад
0
Entity System - я подразумевал как часть менеджера сцены. Отдельно обычно не существует.
Не имеет прямого отношения к сцене, не путать с аналогичной терминологией в юнити. Речь о data-driven организации игровой логики и соответствующем представлении всех игровых объектов. Сцена с её геометрией строится на основе данных из Entity System, но при этом Entity System может содержать не отображаемые на сцене данные и даже существовать отдельно от сцены в случае сервера. Сливать воедино объекты на сцене и игровую логику это дурной тон и больно кусается при масштабировании проекта - даже в движках позволяющих такое, желательно в объектах сцены оставлять только логику, связанную с отображением, а все остальное выносить отдельно.
Система анимаций вынесена отдельно, т.к. она занимается не связанной с физ. движком деятельностью.
Но ведь система анимаций это, как правило, тоже часть визуализатора, как и шейдеры.
0
29
8 лет назад
0
Хорошо. А что интересно? Как взаимодействуют клиент и сервер, какие протоколы используются, в чём их преимущества или всё сразу?)
Да, интересует именно архитектура взаимодействия)
0
10
8 лет назад
Отредактирован ZLOI_DED
0
prog:
Entity System - я подразумевал как часть менеджера сцены. Отдельно обычно не существует.
Не имеет прямого отношения к сцене, не путать с аналогичной терминологией в юнити. Речь о data-driven организации игровой логики и соответствующем представлении всех игровых объектов. Сцена с её геометрией строится на основе данных из Entity System, но при этом Entity System может содержать не отображаемые на сцене данные и даже существовать отдельно от сцены в случае сервера. Сливать воедино объекты на сцене и игровую логику это дурной тон и больно кусается при масштабировании проекта - даже в движках позволяющих такое, желательно в объектах сцены оставлять только логику, связанную с отображением, а все остальное выносить отдельно.
Система анимаций вынесена отдельно, т.к. она занимается не связанной с физ. движком деятельностью.
Но ведь система анимаций это, как правило, тоже часть визуализатора, как и шейдеры.
Всё что является игровой сущностью должно находится на сцене (не обязательно иметь свойства нужные для отображения и пр.). Поэтому я обобщил в менеджер сцены. Сцена логическая, а не визуальная или физическая или какая-нибудь ещё.
А вообще можно переименовать в менеджер игровых сущностей, да, согласен.
А если система анимаций влияет на что-то кроме визуального результата, возвращаемого игроку? Тут не всё так просто.
alexprey:
Хорошо. А что интересно? Как взаимодействуют клиент и сервер, какие протоколы используются, в чём их преимущества или всё сразу?)
Да, интересует именно архитектура взаимодействия)
Ок, обязательно напишу про это :)
2
24
8 лет назад
2
ZLOI_DED, Entity System в чистом виде штука довольно сложная для восприятия. "Сущность" в ней это всего-навсего числовой идентификатор и связанный с ним контейнер для "компонентов", представленных в виде данных, а весь код вынесен в глобальные "системы", которые выбирают интересующие их сущности по набору компонентов и выполняют с ними различные действия. При этом, например, событие нанесения урона цели тоже может быть сущностью - в компоненты этой сущности заносятся такие параметры как источник урона, тип, количество и, конечно, цель, затем соответствующая система выбирает все сущности с компонентами нанесения урона и применяет этот урон к цели, учитывая компоненты цели, которые могут содержать, например, общую защиту от урона или сопротивляемость какому-то конкретному типу урона. После обработки, естественно, сущность для нанесения урона уничтожается. Это не просто менеджер сцены или какая-то отдельная подсистема, это подход к построению архитектуры всей игровой логики. Я не предлагаю подробно писать об этом, особенно если ты сам с этим еще не сталкивался, но нельзя писать об игровых движках и не упомянуть эту тему.
2
10
8 лет назад
2
prog:
ZLOI_DED, Entity System в чистом виде штука довольно сложная для восприятия. "Сущность" в ней это всего-навсего числовой идентификатор и связанный с ним контейнер для "компонентов", представленных в виде данных, а весь код вынесен в глобальные "системы", которые выбирают интересующие их сущности по набору компонентов и выполняют с ними различные действия. При этом, например, событие нанесения урона цели тоже может быть сущностью - в компоненты этой сущности заносятся такие параметры как источник урона, тип, количество и, конечно, цель, затем соответствующая система выбирает все сущности с компонентами нанесения урона и применяет этот урон к цели, учитывая компоненты цели, которые могут содержать, например, общую защиту от урона или сопротивляемость какому-то конкретному типу урона. После обработки, естественно, сущность для нанесения урона уничтожается. Это не просто менеджер сцены или какая-то отдельная подсистема, это подход к построению архитектуры всей игровой логики. Я не предлагаю подробно писать об этом, особенно если ты сам с этим еще не сталкивался, но нельзя писать об игровых движках и не упомянуть эту тему.
Хорошо написал, мне понравилось)
Я понял о чём ты и это в действительности основывается на менеджменте сцены (всё-таки верну это название... оно правильнее будет), системе событий и устройстве ядра.
Просто я не предполагал управление сущностями вне какого-либо контекста, от которого они зависят, поэтому и поместил их внутрь управления сценой.
Если ты имеешь ввиду подход к построению игровой логики, а не конкретную систему движка, то это материал для ещё одного номера, в котором надо обозреть также и другие подходы, сравнить их, определить преимущества и недостатки каждого и т.п.
Так что благодарю, обязательно упомяну об этом подходе в одном из следующих номеров)
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.