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

64

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

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

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

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


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

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

  • 1 Скорость

  • 2 Начальная позиция того места, откуда он стреляет

  • 3 спрайт текстуры

  • 4 Эффект удара

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

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


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

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

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

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

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

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

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


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

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

Эрик
источник
16
Обратите внимание, что даже сегодня большинство игр не имитируют полет пуль. Для всего, что считается «достаточно быстрым», вместо этого выполняется простой поиск совпадений - в основном предполагается, что воздействие происходит одновременно с нажатием на курок. В любом случае «сотни или тысячи пуль» на самом деле не так уж и велики - это то, что было в играх с самых ранних приставок (различных игр «пуля-ад»), в тысячи раз менее мощных, чем современные машины. Вам просто нужно убедиться, что вы выполняете как можно меньше работы для каждой пули :)
Luaan
42
Пули обычно работают по pew-pew-pewтехнологии :)
MonkeyZeus
5
Там никогда не бывают сотни или тысячи пуль одновременно. Там нет пистолета, который стреляет их так быстро. Даже могучая фаланга достигает 75 пуль в секунду. Исходя из «Эффективной дальности стрельбы», указанной в Википедии, пули летят максимум около 3 секунд, поэтому «Фаланга» может одновременно поднять 225 пуль в воздух. M16 достигает максимума около 12 выстрелов в секунду и не может поддерживать эту скорость (максимум для устойчивого огня составляет 0,25 об / сек). Просто не так много оружия, стреляющего одновременно!
Корт Аммон
3
Просто чтобы указать на это, никогда не стоит делать объекты отдельными классами, когда они так просты. Гораздо лучше иметь один экземпляр bulletField для каждого типа маркера. Незначительные издержки в длине кода и тому подобное сэкономят вам лишнее 4-байтовое слово на маркер (если type является целым числом). Кроме того, один объект может легко сканировать список.
Великая утка
4
@Cort - это правда, если предположить, что в игровом пространстве есть только одно огнестрельное оружие. ОП упоминал такие игры, как Battlefield и CoD, где десятки игроков могли одновременно стрелять из автоматического оружия. Не исключено смешное число, если каждый раунд фактически учитывался в космосе.
Джесси Уильямс

Ответы:

78

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

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

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

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

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

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

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

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

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

Том К
источник
12
Я должен не согласиться с 5), что на самом деле просто усложняет ситуацию в современных играх. В ранних шутерах это было приемлемо, в настоящее время даже ХПК позволяет игрокам стрелять через деревянные стены. 6) было бы неприемлемо для любой конкурентной системы, хотя это было бы редкой проблемой.
SBoss
17
@SBoss затем перефразирую: «Как только они попадают во что-то, в которое они не могут проникнуть, я также могу истечь их, чтобы у них было конечное время жизни». И для 6 вы можете получить наихудший случай, ограничив максимальную скорострельность на персонажа, а затем сохранив массив длиныnum_characters * max_bullets_per_character
фрик с трещоткой
14
@SBoss Я думаю, что # 6 больше, например. Космические игры сверху вниз, где медленно движущаяся пуля может пролететь большое расстояние за кадром, прежде чем ударить что-то / исчезнуть. Очевидно, что это не проблема в играх типа CoD, где пули движутся быстро и быстро достигают границ мира.
BlueRaja - Дэнни Пфлугхофт
1
Подавляющее большинство игр НЕ моделируют пули (внешнюю баллистику) вообще. Большинство игр используют технику, называемую «сканирование хитов».
Арон
44

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

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

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

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

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

щетинка
источник
Информация о шаблонах проектирования, Hitscan и четырех / восьми деревьях действительно помогает. Также спасибо за информацию!
Эрик
8
Если вы не предъявляете иск на попадание, но имитируете снаряды, они могут искривляться через тонкие объекты, потому что они движутся так быстро. В этом случае помните, что все в играх - подделка. Даже если длина пули составляет всего несколько сантиметров, вы можете обнаружить столкновение, как если бы пуля была длиной в метр. Таким образом, вы все равно можете делать приятные капли и моделировать время полета, не беспокоясь о том, как пули будут искривляться сквозь объекты, не ударяя их :).
Рой Т.
2
Существуют ли игры, в которых физика пуль (в отличие, скажем, от пушек) учитывает такие вещи, как гравитация (падение пули), сопротивление воздуха? (То есть игры, кроме специализированных игр, в которых основное внимание уделяется точной стрельбе по мишеням или что-то в этом роде: FPS и т. Д.) Я не геймер, но меня удивляет, что этот уровень точности (даже иногда) необходим.
Давидбак
3
@davidbak: это сильно зависит от типичной встречи в игре и реализма, ожидаемого от жанра игры. Если вы в основном (только?) Сражаетесь в ближнем бою, то действительно, такой уровень верности не нужен. Но если существует вариант для боя на большие расстояния (например, снайперы или лучники в более RPG-подобной обстановке), в настоящее время ожидается влияние гравитации на ракеты. Если вы нацелите свою ракетную установку вверх, вы все равно ожидаете, что ракета приземлится и взорвется где-нибудь, не так ли? Тем не менее, траектории не всегда рассчитываются из реальной физики, только приближение (по соображениям производительности)
hoffmale
1
@davidbak Battlefield, так как у Bad Company 2 было падение пули. Оба для винтовок, пистолета, снарядов, ракет, всего. Battlefield 3 бесплатен на Origin, вы можете проверить (IIRC). Battlefield 4, конечно, также имеет эту «особенность». Другая игра, где вы можете увидеть это "Sniper Elite". 2 или 3 - новые названия. Физика играет важную роль в этой игре.
Apache
7

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

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

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

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

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

Так что бы скорость вертолета!

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

user1118321
источник
6

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

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

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

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

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

pjc50
источник
Интересно , как бензопила работала в этом контексте
reas0n
1
IIRC, настоящая проблема с первой сетью обречена на то, что она избавила от необходимости посылать каждый пакет отдельно каждому противнику, используя вместо этого широковещательные пакеты. Это уменьшало количество отправляемых пакетов, но, к сожалению, создавало значительную нагрузку на процессор на каждой машине в сети, включая те, которые не играли в игру.
суперкат
1

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

Мой метод

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

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

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

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

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

Обратите внимание на разные методы

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

С 3D-моделями, которые могут иметь сложные хитбоксы, стандартно проверять столкновения на простом ограничивающем прямоугольнике FIRST, и, если это удастся, перейти к более «детальному» обнаружению столкновений.

TheCatOfWar
источник
0

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

Микаэл
источник