На движке Source (и это его предшественник, goldsrc, quake) игровые объекты делятся на два типа: мир и сущности. Мир - это геометрия карты, а сущности - это игроки, частицы, звуки, очки и т. Д. (Для движка Source).
Каждая сущность имеет функцию мышления , которая выполняет всю логику для этой сущности.
Таким образом, если все, что необходимо обработать, происходит из базового класса с функцией Think, игровой движок может хранить все в списке и в каждом кадре циклически проходить по нему и вызывать эту функцию.
На первый взгляд, эта идея разумна, но может потребовать слишком много ресурсов, если в игре много сущностей.
Итак, как движок вроде Source заботится (обрабатывает, обновляет, рисует и т. Д.) Игровых объектов?
<some commercial engine>
это?Ответы:
В общем, другого способа сделать это практически нет - вам придется проходить циклы и вызывать
think()
каждую сущность хотя бы раз в несколько кадров.Вы можете поместить сущности в их собственный поток, но тогда у вас будет целый кошмар синхронизации состояний, который определенно не стоит этого.
Вот почему механизм Source устанавливает жесткое ограничение на количество сущностей, которые могут существовать одновременно : 4096 сущностей, из которых только половина (2048) может быть объединена в сеть. Пройдите любой из этих ограничений, и игра вылетит.
Вот почему при создании карты рекомендуется не использовать более 800 объектов.
источник
Упомянутые вами шаги, скорее всего, выполняются в отдельных движках Просто у простых игровых движков их обычно бывает за один проход. Ваша последовательность
становится
Физический двигатель заботится о позициях и размерах.
Game Logic Engine заботится о том, чтобы интерпретировать, что физический движок изменился (он может помешать некоторым путевым точкам ...), какие цели преследуют персонажи и какое поведение они должны выполнять , он запускает запланированные сценарии (эта функция мышления ).
Drawing Engine рисует, какие объекты видимы, и он знает, какие объекты видимы, потому что движки Quake обманывают здесь (см. Раздел Draw).
Мой вам совет - лучше изучить, как выполняются симуляции, а не игровые движки. Существует огромная поп-культура, связанная с разработкой игр, и игровые движки сделаны на императивных языках (из-за традиций и скорости); так что мне было более поучительно получать хорошие учебники (скорее теорию) и ТОГДА смотреть на движки (практика), а не смотреть на движки и ломать голову часами, как они это делали.
физика
Целостное представление об итерациях всех сущностей и их выполнении может привести к проблемам. Будут конфликты и тд. Я верю, что у Valve есть Havok, и я думаю, что Havok заботится о достаточно правильной физике.
Считать
Функция Think запускается, когда время в игре равно времени в следующем разуме . Так работает в движке Quake, а движок Quake является основой для двигателей Half Life. Это НЕ запускается каждый раз.
Внутренне это должна быть простая итерация по списку объектов и проверка, прошло ли время для вызова функции Think. Временная сложность будет O (N), где N - количество объектов.
Если существует очень большое количество объектов, вы должны измерить, насколько это улучшит fps. Обратите внимание, что по закону Амдала это потенциально невидимое ускорение. Я имею в виду, вы просто перебираете все элементы, уменьшаете и проверяете одно число.
Я бы ускорил его, отсортировав сущности по nextthink (создайте список указателей на сущности и сортируйте их каждый раз; не массив сущностей, потому что сущности могут изменить их nextthink в любое время, поэтому для их реорганизации в массиве требуется O (N) вместо O ( 1) в списке).
Вы также должны посмотреть на O (1) планировщик в Linux .
Рисовать
Двигатель рисует то, что приблизительно видно из области, в которой находится камера. Уровень игры - это разбиение на дерево, а область - это лист этого дерева. Я не буду беспокоить Вас подробностями об этом ... Так что, если сущность видима, она помещается в набор видимых сущностей, и они рисуются.
Они хранят, какие области являются потенциально видимыми областями. Это называется «потенциально видимый набор», сокращенно PVS . Есть визуализация PVS , зеленая капсула игрока и вокруг него отображается то, что содержит его PVS.
источник
На самом деле помещать все в один большой список обычно меньше, чем хотелось бы; если бы вы должны были группировать объекты в списках, например, по их типу, вы могли бы лучше распределить обработку по нескольким потокам. Например, если вы знаете, что все сущности типа Foo никогда не взаимодействуют с какими-либо другими сущностями на этапе моделирования, вы можете полностью разгрузить их. Если бы они были разбросаны волей-неволей по какому-то большому единственному списку, сделать это было бы гораздо сложнее.
Вам не обязательно даже выводить все из общего базового класса в этот момент; Источник идет слишком долго с наследованием злоупотребления для того, что в противном случае может быть реализовано в качестве данных в этом отношении.
Конечно, у вас всегда будет верхний предел количества объектов, которые вы можете обработать на кадр, даже если вы начнете перекладывать работу на другие ядра. Обойти это невозможно, вам просто нужно иметь представление о том, что это за предел в вашей реализации, и предпринимать шаги по его устранению (надлежащая выборка этапов обработки для объектов, которые в них не нуждаются, избегая чрезмерной гранулярности в объектах и т. Д. так далее).
источник
То, что вы должны принять во внимание, и это после последовательности мыслей предыдущих ответов заключается в том, что ваша производительность также будет зависеть от того, когда и как вы называете эти мыслительные функции.
Просматривая ссылку, которую вы разместили на движке исходного кода, вы также можете прочитать, что вы можете настроить время мышления и разные контексты мышления для каждой из ваших сущностей, помимо очевидного жесткого ограничения, на которое уже указывал кто-то, это будет ключом к достижению большей производительности. с большим числом объектов, либо путем создания пошаговых обновлений, которые распространяют ресурсоемкую обработку через несколько кадров выполнения, либо путем исключения ненужной обработки в зависимости от текущего контекста (т.е. объекты, которые находятся слишком далеко или за пределами восприятия игрока, не нуждаются тот же уровень «детализации мысли», что и у персонажей, которые находятся рядом с игроком, просто не увидит персонажа, находящегося в 2 милях от него, ковыряющегося в носу).
Есть и другие, более специфические уровни оптимизации, в зависимости от конкретной игровой логики и ситуации.
источник