Как работают пули в видеоиграх?

Я столкнулся с этим вопросом, когда я разрабатывал видеоигру на C #.

Если мы рассматриваем такие игры, как Battlefield или Call of Duty , одновременно летают сотни или даже тысячи пуль. События срабатывают постоянно, и, как я знаю, это отнимает много вычислительной мощности - или это так? Я хочу знать, как различные разработчики игр управляют (2D и 3D) пулями и наиболее эффективный метод для каждого из них.

Я прочитал вопрос Как моделируются пули в видеоиграх? , но он не затрагивает, как работают пули с точки зрения дизайна программы.

У меня было несколько идей, но у каждого есть свои недостатки:


Самый эффективный метод, который я мог бы подумать (для 2D-игр):

Скажем, я должен был создать класс Bullet, и, как бы длинный пользователь не нажал кнопку, каждые 0,01 секунды был создан объект Bullet. Эта пуля имеет:

  • 1 Скорость

  • 2 Исходное положение, где он снимается с

  • 3 текстура спрайтов

  • 4 Эффект on-hit

Поскольку пуля будет ее собственным классом, она может управлять самими рисовальщиками, движущимися и действиями.

Не сложно ли процессору обработать тысячи этих объектов, которые будут созданы, а затем уничтожены (когда срабатывает эффект on-hit)? ОЗУ?


Эффективный метод для 3D-игр. Еще одна мысль, которая у меня была:

Давайте скажем, что я создаю класс оружия. Это оружие имеет различные функции, некоторые из которых:

  • 1 Определите, куда нацеливается оружие, и определите, смотрит ли он на цель

  • 2 Запуск анимации стрельбы пистолета

  • 3 Имеет метод doDamage (), который указывает что-то, чтобы вычесть здоровье из того, на что указывает пистолет на

  • 4 Уведомляет класс анимации пули при нажатии кнопки

Тогда я мог бы создать статический класс, например BulletAnimation, который мог получить уведомление, откуда пистолет, который его запускал, там, где это оружие указано (для пункта назначения пули), и информацию о соответствующем спрайте и скорости для использования для пули. Затем этот класс рисует спрайты (на новой ветке, возможно, idk) на основе обеих позиций и желаемого спрайта, чтобы имитировать пулю, выпущенную из пистолета.


Последнему кажется сложнее закодировать код, и не нужно ли требовать много вычислительной мощности, чтобы постоянно вызывать статику, чтобы делать это за тысячи пуль одновременно? Получение постоянных обновлений как в начальных, так и в конечных положениях было бы затруднительным.

Мой вопрос в том, что самый эффективный способ создания создателей игры? Изменяется ли этот метод от 2D до 3D-игр?

62 голоса | спросил Eric 1 J000000Friday16 2016, 03:33:48

6 ответов


76

Я, конечно же, могу понять, почему вы думаете, что было бы сложно имитировать их, но есть достаточно ограничений на пули (все снаряды, на самом деле), чтобы сделать их проще.

  1. Они обычно моделируются как одна точка, а не как что-то с томом. Это значительно облегчает обнаружение столкновений, так как теперь мне нужно делать столкновения с очень простыми поверхностями, такими как линия против круга.

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

  3. Так как все снаряды будут очень похожи, мы можем предварительно выделить их, чтобы избежать всех накладных расходов на их динамическое создание. Я могу выделить массив из 1000 снарядов, и теперь к ним можно получить доступ только с индексом, и они все последовательны в памяти, поэтому их обработка будет быстрой.

  4. У них есть фиксированное время жизни /диапазон, поэтому я могу истечь старые патроны и быстро перерабатывать память в новые патроны.

  5. Как только они что-то ударят, я также могу их закончить, поэтому они имеют конечное время жизни.

  6. Поскольку мы знаем, когда они были созданы, если нам нужны новые, и у нас нет бесплатного в нашем предварительно распределенном списке, я могу просто захватить самые старые и переработать их, и люди не будут обратите внимание, что пули истекают немного раньше.

  7. Они отображаются как спрайты (обычно) или как низкополимерные модели, и занимают очень мало места на экране, поэтому они быстро визуализируются.

Принимая во внимание все эти вещи, пули, как правило, относительно дешевы. Если бы наш бюджет когда-либо был поглощен пулями и их рендерингом, мы бы просто перепроектировали его, чтобы ограничить количество выстрелов, которые вы можете стрелять одновременно (вы увидите это во многих старых аркадных играх), используйте оружие луча, которое мгновенно перемещается , или замедлить темпы пожара, чтобы убедиться, что мы остаемся в пределах бюджета.

ответил Tom K 1 J000000Friday16 2016, 06:03:04
42

Возможно, одним из наиболее эффективных способов реализации пули является использование так называемого hitscan . Это довольно просто в его реализации - когда вы стреляете, вы проверяете, к чему стремится пушка (возможно, используя луч, чтобы найти ближайший объект /объект /сетку), а затем вы ударили его, нанеся урон. Если вы хотите, чтобы это выглядело скорее как фактическая, быстро движущаяся невидимая пуля была уволена, вы можете подделать ее, добавив небольшую задержку, зависящую от расстояния, прежде чем наносить урон.

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

Следующим подходом было бы моделирование выстреливаемой пули как снаряд, который моделируется как его собственный объект /объект, подверженный столкновению, и, возможно, гравитация и /или сопротивление воздуха, которое изменяет его направление и скорость. Это более сложный подход, чем обратный захват из-за дополнительных физических уравнений и более ресурсоемкий из-за наличия фактического объекта пули, но может обеспечить более реалистичные пули.

Что касается управления столкновениями между пулями на основе снарядов и другими объектами в игре, обнаружение столкновения может быть значительно упрощено путем сортировки ваших объектов в quad или октетов . Octrees в основном используются в 3D-играх, а квадранты могут использоваться в играх 2d или 3d. Преимущества использования одного из этих деревьев в том, что вы можете значительно уменьшить количество возможных проверок столкновения. Например, если у вас есть 20 объектов, действующих на уровне, без использования одного из этих деревьев, вам нужно будет проверить все 20 для столкновения с пулей. Разделение 20 объектов среди листьев (конечных узлов) дерева, и вы можете уменьшить количество проверок до тех пор, пока многие объекты не будут присутствовать в том же листе, что и маркер.

Что касается этих подходов - хитов и снарядов, то они могут свободно использоваться в играх 2d или 3d. Это больше зависит от того, что такое оружие, и как создатель решил, что оружие должно функционировать.

ответил Seta 1 J000000Friday16 2016, 06:27:13
7

Я ни в коем случае не специалист, но чтобы ответить на ваш вопрос, да, вам понадобится много из тех вещей, которые вы упомянули.

Для вашего 2D-примера у вас может быть положение и скорость для пули. (Вам также может потребоваться время жизни или максимальное расстояние, в зависимости от того, как вы реализуете свои пули.) Обычно это включает в себя 2 (x, y) значения. Если они были float, это 16 байт. Если у вас 100 пуль, это всего лишь 1600 байт или около 1,5 тысяч. Сегодня на машине ничего нет.

Затем вы упомянете спрайты. Вам понадобится только один спрайт для представления каждой пули. Его размер будет зависеть от глубины бит, на которую вы рисуете, и от того, насколько большой он должен появиться на экране. Даже без сжатия, скажем, 256х256 в полном поплавке 32-бит на канал, это 1 МБ для спрайта. (И это было бы очень большим!) Вы бы нарисовали один и тот же спрайт в каждом месте пули, но для каждой копии спрайта не требуется дополнительная память. Это было бы похоже на эффект on-hit.

Вы указываете стрельбу каждые 0,01 секунды. Это будет 100 пуль в секунду от вашего оружия. Даже для футуристического оружия это довольно много! Согласно этой статье в википедии :

  

Когда триггер вытягивается, скорость, с которой стреляют выстрелы, является циклической скоростью. Типичные циклические скорости стрельбы составляют 600 - 900 об /мин для штурмовых винтовок, в некоторых случаях 1000-1100 об /мин, 900-1 200 об /мин для автоматов и машинных пистолетов и 600-1,200 об /мин для пулеметов. M134 Минигены, установленные на ударных вертолетах и ​​других боевых машинах, могут достичь скорости стрельбы более 100 выстрелов в секунду (6000 об /мин).

Так будет скорость атаки вертолета!

Для такого большого мира, как вы упомянули в Battlefield /Call of Duty /и т. д., они могут рассчитать все эти позиции маркера, но не нарисовать их все, если действие находится далеко. Или они не могут имитировать их, пока не приблизитесь. (Я должен признать, что я немного угадываю эту часть, поскольку я не работал над чем-то большим.)

ответил user1118321 1 J000000Friday16 2016, 06:04:04
6
  

Не сложно ли процессору обработать тысячи этих объектов, которые будут созданы, а затем уничтожены (когда срабатывает эффект on-hit)? ОЗУ?

Я думаю, вы недооцениваете, насколько быстрыми являются компьютеры. Это было иногда проблемой для систем 80-х и 90-х годов. Частично поэтому оригинальные космические захватчики не позволят вам выстрелить еще одну пулю, пока не ударит текущий. Некоторые игры пострадали от «замедления», если на экране было слишком много спрайтов.

В настоящее время, правда? У вас достаточно вычислительной мощности для тысяч операций на пиксель , которые необходимы для текстурирования и освещения. Нет никаких проблем с тысячами движущихся объектов; это позволяет вам разрушать рельеф (например, Red Faction), где каждый фрагмент выполняет обработку столкновений с другими фрагментами и следует за баллистической кривой.

Вы должны быть осторожны алгоритмически - вы не можете сделать наивный подход к проверке каждого объекта против любого другого объекта, когда у вас тысячи объектов. Пули обычно не проверяют наличие столкновений с другими пулями.

Небольшой анекдот: первая версия сетевой Doom (оригинал 90-х годов) отправила один пакет по сети для каждой пули. Когда один или несколько игроков получили пулемет, это может легко перегрузить сеть. 90-е годы были полны людей, которые незаконно играли Doom в университетских или рабочих сетях, столкнувшись с проблемами со своими сетевыми администраторами, когда сеть стала непригодной.

ответил pjc50 1 J000000Friday16 2016, 12:35:36
1

Я далек от эксперта, но в свободное время я работал над многопользовательской 2D-шутер.

Мой метод

Существуют разные классы пули между клиентом и сервером (даже при игре в автономном режиме экземпляр сервера запускается в отдельном процессе и связан с основной игрой).

Каждый тик (60 в секунду) клиент выполняет опору между указателем мыши игрока и центром экрана (где их характер), и это часть информации, отправленной на сервер. Если игрок также стреляет в этот момент (при условии, что оружие загружено и готово), создается экземпляр пули на стороне сервера с просто некоторыми координатами и базовым урон (который происходит от статистики оружия, которое было снято Это). Затем экземпляр пули использует некоторые математические функции для вычисления скорости X и Y от подшипника, который мы собрали от клиента.

Для каждого последующего тика пуля движется сама по этим координатам и уменьшает ее базовый урон на предопределенную сумму. Если это значение будет ниже 1 или если оно ударит по твердому объекту в мире, экземпляр пули будет удален, и, поскольку столкновение с точками тестирования невероятно дешево в 2D, даже быстрое огневое оружие оказывает незначительное влияние на производительность.

Что касается клиента, информация о пули фактически не принимается по сети (это оказалось расточительным при тестировании), вместо этого в качестве части обновления для каждого тика у каждого символа есть «fired» Boolean, который, если true, клиент создает локальный объект bullet, который работает почти так же, как и серверные, с той лишь разницей, что он имеет спрайт.

Это означает, что хотя пуля, которую вы видите, не является полностью точным представлением ее на сервере, любая разница будет едва заметна, если вообще для игрока, а преимущества сети перевешивают любые несоответствия.

Примечание для разных методов

Некоторые игры, в том числе мои собственные, перемещают маркеры по каждому тику, как если бы они были физическими объектами, тогда как другие просто создавали вектор в направлении съемки или вычисляли весь путь пули в тике, который он создан, например в играх Counter-Strike. Есть несколько небольших трюков на стороне клиента, чтобы замаскировать его, например, анимацию пули, но для всех целей каждая цель - это просто ответил TheCatOfWar 3 J000000Sunday16 2016, 12:25:32

0

Это называется обнаружением столкновения. 8-разрядные компьютеры сделали это с использованием игровой графики в аппаратных средствах. Современные игровые движки используют физические двигатели и линейную алгебру. Текущее направление оружия представлено в виде 3D-вектора. Это обеспечивает бесконечную линию в направлении огня. Каждый движущийся объект имеет одну или более ограничительную сферу, поскольку это самый простой объект для обнаружения столкновения с линией. Если они пересекаются, это хит, а если нет, то никакого удара нет. Но декорации могут быть в пути, поэтому это нужно также проверить (используя иерархические ограничивающие тома). Ближайшим объектом, который имеет пересечение, является тот, который был поражен.

ответил Mikael 4 J000000Monday16 2016, 15:14:52

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132