Як працюють кулі у відеоіграх?


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
Зауважте, що навіть сьогодні більшість ігор не імітують політ куль. Для всього, що вважається "досить швидким", натомість виконується простий скан-хіт - в основному, передбачається, що удар відбувається одночасно з натисканням на спусковий гачок. У будь-якому випадку "сотні чи тисячі куль" насправді не велика кількість - це те, що в іграх було з дуже ранніх консолей (різні ігри з пекельними кулями), в тисячі разів менш потужні, ніж сьогоднішні машини. Вам просто потрібно переконатися, що ви робите якомога менше роботи за кулю :)
Луань,

42
Кулі зазвичай працюють за допомогою pew-pew-pewтехнології :)
MonkeyZeus

5
Ніколи сотні чи тисячі куль не пролітають одночасно. Немає жодного пістолета, який стріляє з них так швидко. Навіть могутня Фаланга вискакує з 75 куль в секунду. На основі "Ефективного дальності стрільби", переліченого у Вікіпедії, кулі летять приблизно 3 секунди максимум, тож Фаланга може одночасно випустити 225 куль у повітря. M16 вискакує близько 12 раундів / сек і не може витримати цю швидкість (максимум для стійкого вогню - 0,25 об. / Сек). Просто не так багато рушниць стріляють у будь-який час!
Корт Аммон

3
Тільки щоб це зазначити, ніколи не буває складати об’єкти індивідуальними класами, коли вони такі прості. Набагато краще мати один екземпляр bulletField для кожного типу кулі. Невеликі накладні витрати в довжині коду і багато іншого допоможуть вам заощадити додаткові 4-байтні слова на кулю (якщо тип - це ціле число). Крім того, один об’єкт може легко сканувати список.
Велика качка

4
@Cort - це правда припустимо, що в ігровому просторі є лише одна вогнепальна зброя. В ОП згадувалися такі ігри, як Battlefield та CoD, де десятки гравців могли одночасно стріляти з автоматичних гармат. Це нерозумно, щоб було смішне число, якщо кожен раунд насправді рахувався фізично в космосі.
Джессі Вільямс

Відповіді:


78

Я, безумовно, можу зрозуміти, чому ви подумаєте, що важко було б імітувати їх, але для кулі (справді всі снаряди, справді) досить обмежень, щоб зробити їх простішими.

  1. Вони, як правило, імітуються як окрема точка, а не як об'єм. Це робить розпізнавання зіткнень значно простішим, оскільки тепер мені потрібно робити лише зіткнення з дуже простими поверхнями, такими як лінія проти кола.

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

  3. Оскільки всі снаряди будуть дуже схожими, ми можемо попередньо їх розподілити, щоб уникнути всіх накладних витрат на їх динамічне створення. Я можу виділити масив з 1000 снарядів, і тепер до них можна отримати лише індекс, і всі вони послідовні в пам'яті, тому обробка їх буде швидкою.

  4. Вони мають фіксований термін служби / діапазон, тому я можу закінчити термін дії старих куль і переробити пам'ять у нові кулі дуже швидко.

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

  6. Оскільки ми знаємо, коли вони були створені, якщо нам потрібні нові, і в нашому попередньо виділеному списку немає вільного, я можу просто захопити найстаріші та переробити їх, і люди не помітять, чи кулі закінчуються трохи рано .

  7. Вони надаються у вигляді спрайтів (як правило) або як низькополітичні моделі, і займають дуже мало місця на екрані, тому вони швидко відображаються.

Враховуючи всі ці речі, кулі, як правило, відносно дешеві. Якщо наш бюджет коли-небудь споживається кулями та їх рендерінгом, ми зазвичай просто переробляємо його, щоб обмежити кількість пострілів, які ви можете стріляти за один раз (це ви побачите у багатьох старих аркадних іграх), використовуйте променеву зброю, яка рухається миттєво або сповільнити рівень пожежі, щоб переконатися, що ми залишаємося в межах бюджету.


12
Я повинен не погодитися з 5), що насправді просто ускладнює всю справу в сучасних іграх. У попередніх стрільців це було прийнятно, а нині навіть COD дозволяє гравцям стріляти через дерев'яні стіни. 6) було б неприйнятним для будь-якої конкурентної системи, хоча це було б рідкісною проблемою.
SBoss

17
@SBoss потім перефразовує: "Після того, як вони потрапляють у щось, у що не можуть проникнути, я також можу їх закінчити, тому вони мають обмежений термін служби". А за 6 років ви можете отримати найгірший випадок, обмеживши максимальну швидкість вогню на персонажа, а потім зберегти масив довжиниnum_characters * max_bullets_per_character
храповик виродка

14
@SBoss Я думаю, що №6 більше для напр. космічні ігри згори вниз, де куля, що рухається повільно, може проїхати велику відстань поза екраном, перш ніж щось вдарити / зникнути. Очевидно, це не проблема в іграх типу CoD, де кулі швидко рухаються і швидко досягають меж світу.
BlueRaja - Danny Pflughoeft

1
Переважна більшість ігор взагалі НЕ моделюють кулі (зовнішня балістика). У більшості ігор використовується техніка, яка називається "сканування хітом".
Арон

45

Напевно, одним із найефективніших способів реалізації куль є використання того, що відомо як хіт-парад . Він досить простий у своїй реалізації - коли ви стріляєте, ви перевіряєте, на що націлений пістолет (можливо, використовуючи промінь, щоб знайти найближчий об'єкт / об’єкт / сітку), а потім ви «ударяєте» його, роблячи шкоду. Якщо ви хочете, щоб це виглядало більше схожим на справжню, швидкострільну кулю невидимою кулею, ви можете підробити її, додавши невелику затримку, залежну від відстані, перш ніж завдати шкоди.

Цей підхід, по суті, передбачає, що вистрілений снаряд має нескінченну швидкість, і, як правило, використовується для таких видів зброї, як лазери та пучки / гармати, а може бути, і для деяких видів снайперських гвинтівок .

Наступним підходом було б моделювання вистріленої кулі як снаряда, яка моделюється як власна сутність / об'єкт, який піддається зіткненню, і, можливо, сила тяжіння та / або опір повітря, що змінює його напрям і швидкість. Він складніший, ніж підхід хіт-канів через додаткові рівняння фізики, та більш ресурсомісткий через те, що він є фактичним об'єктом кулі, але може забезпечити реалістичніші кулі.

Що стосується управління зіткненнями між кулями, що базуються на снаряді, та іншими предметами в грі, то виявлення зіткнень може бути значно спрощено шляхом сортування об'єктів у квадрати чи октриси . Octrees в основному використовуються в 3d-іграх, тоді як кваддри можуть використовуватися в 2d або 3d-іграх. Переваги використання одного з цих дерев полягає в тому, що ви можете значно зменшити кількість можливих перевірок на зіткнення. Наприклад, якщо у вас 20 об’єктів, що діють на рівні, не використовуючи жодне з цих дерев, вам доведеться перевірити всі 20 на зіткнення з кулею. Розділивши 20 об’єктів між листям (кінцевими вузлами) дерева, ви можете зменшити кількість перевірок до тих пір, хоча багато об’єктів присутні в тому ж листі, що і куля.

Що стосується цих підходів - сканування ударів і снарядів, обидва можна вільно використовувати в 2d або 3d іграх. Це більше залежить від того, що таке зброя, і як творець вирішив, що зброя функціонує.


Інформація про модель дизайну, Hitscan та квадрати / октриси справді допомагає. Також дякую за інформацію!
Ерік

8
Якщо ви не подаєте до суду на ударний удар, але імітуєте снаряди, вони можуть перекидатися через тонкі предмети, оскільки вони рухаються так швидко. У такому випадку пам’ятайте, що все, що в іграх є фальшивим. Незважаючи на те, що куля завдовжки всього кілька сантиметрів, ви можете робити виявлення зіткнення так, ніби куля завдовжки метра. Таким чином, ви все ще можете зробити приємне падіння кулі та час польоту імітації, не турбуючись над тим, щоб кулі перекочувались через об’єкти, не вражаючи їх :).
Рой Т.

2
Чи є ігри, де фізика куль (на відміну, скажімо, від гарматних снарядів) поважає такі речі, як гравітація (падіння кулі), опір повітря? (Тобто ігри, окрім спеціальних ігор, де в центрі уваги є точність стрільби по мішені чи щось подібне: FPS тощо). Я не геймер, але я здивований, що такий рівень вірності (навіть іноді) потрібен.
davidbak

3
@davidbak: сильно залежить від типової зустрічі в грі та реалізму, очікуваного від ігрового жанру. Якщо ви в основному (тільки?) Ведете боротьбу з близькими кварталами, то справді цей рівень вірності не потрібен. Але якщо існує можливість ведення бою на великій дальності (наприклад, снайпери або лучники у більш схожих на РПГ умовах), гравітація, що впливає на ракети, зараз очікується. Якщо ви націлите свою ракетну зброю вгору, ви все одно очікуєте, що ракета десь приземлиться і вибухне, ні? Все-таки траєкторії не завжди обчислюються з реальної фізики, а лише наближення (з міркувань продуктивності)
hoffmale

1
@davidbak Battlefield, оскільки у Bad Company 2 було падіння кулі. І для гвинтівки, і пістолета, і снарядів, і ракет. Battlefield 3 безкоштовно на Origin, ви можете перевірити (IIRC). Звичайно, Battlefield 4 також має цю особливість. Інша гра, де ви можете це побачити, - "Sniper Elite". 2 або 3 - новіші назви. Фізика відіграє важливу роль у цій грі.
Apache

7

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

Для вашого двовимірного прикладу ви могли мати положення і швидкість для кулі. (Можливо, вам також знадобиться тривалість життя або максимальна відстань, залежно від того, як ви реалізуєте свої кулі.) Це, як правило, передбачає 2 (x, y) значення. Якщо вони були поплавцями, це 16 байт. Якщо у вас 100 куль, це всього 1600 байт або близько 1,5 к. Це сьогодні нічого на машині.

Далі ви згадуєте спрайтів. Вам знадобиться лише один спрайт для представлення кожної кулі. Його розмір залежатиме від глибини біта, на якій ви малюєте, і від того, наскільки великим він повинен бути на екрані. Навіть нестиснений, скажімо, 256x256 з 32-бітовим каналом у повному плаванні, це 1 МБ для спрайту. (І це було б дуже велико!) Ви б намалювали один і той же спрайт у кожному місці кулі, але це не потребує додаткової пам'яті для кожної копії спрайта. Це було б подібним ефектом від удару.

Ви згадуєте стрільбу кожні 0,01 секунди. Це було б 100 куль в секунду від вашої зброї. Навіть для футуристичної зброї це досить багато! Відповідно до цієї статті у Вікіпедії :

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

Так що це швидкість атаки вертольота!

У такому великому світі, як ви згадуєте в Battlefield / Call of Duty / тощо., Вони можуть обчислити всі ці позиції кулі, але не намалювати їх усіх, якщо дія буде далеко. Або вони можуть не імітувати їх, поки ви не наблизитесь. (Я мушу визнати, що я трохи здогадуюся над цією частиною, оскільки я не працював над чимось великим.)


6

Чи не буде важко процесору обробити тисячі цих об'єктів, які інстанціюються, а потім знищуються (коли спрацьовує ефект при натисканні)? Простір оперативної пам’яті?

Я думаю, ти недооцінюєш, наскільки швидкі комп’ютери. Це було іноді проблема на системах 80 - х і 90 - х років. Частково тому, що оригінальні космічні загарбники не дозволять вам вистрілити ще одну кулю, поки поточна не потрапила. Деякі ігри страждали від «уповільнення», якщо на екрані було занадто багато спрайтів.

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

Вам потрібно бути обережним алгоритмічно - ви не можете робити наївний підхід перевіряти кожен об'єкт проти кожного іншого об'єкта, коли у вас є тисячі об'єктів. Кулі зазвичай не перевіряють на предмет зіткнення з іншими куль.

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


Цікаво, як працювала бензопила в цьому контексті
reason0n

1
IIRC, справжня проблема першої мережевої думи полягає в тому, що вона уникала необхідності надсилати кожен пакет окремо кожному протилежному гравцеві, використовуючи замість цього широкомовні пакети. Це зменшило кількість відправлених пакетів, але, на жаль, спричинило значне навантаження процесора на кожну машину в мережі, включаючи і ті, які не грали в гру.
supercat

1

Я далеко не експерт, але у вільний час працюю над багатокористувацькою 2D-стрілялкою.

Мій метод

Між клієнтом і сервером існують різні класи кулей (навіть при програванні в автономному режимі екземпляр сервера запускається в окремий процес і підключається до 'головної' гри).

Кожен галочок (60 в секунду) клієнт визначає опору між вказівником миші гравця та центром екрана (де їх персонаж), і це частина інформації, що надсилається на сервер. Якщо гравець також стріляє в цей момент (якщо припустити, що зброя завантажена і готова), створюється екземпляр кулі на стороні сервера, з просто деякими координатами та базовим збитком (який виходить із статистики зброї, яка вистрілила. це). Потім екземпляр кулі використовує деякі математичні функції для обчислення швидкості X і Y з підшипника, який ми зібрали від клієнта.

Для кожного наступного галочки куля переміщується за цими координатами і зменшує базовий урон на попередньо визначену кількість. Якщо ця величина опускається нижче 1, або якщо вона потрапляє на твердий предмет у світі, екземпляр кулі видаляється, і оскільки зіткнення з точки тестування неймовірно дешеві в 2D, навіть зброя швидкого стрільби має незначний вплив на продуктивність.

Що стосується клієнта, інформація про кулі насправді не надходить через мережу (вона виявилася марною при тестуванні), натомість як частина оновлення за тик кожен символ має "звільнений" булевий формат, який, якщо правда, клієнт створює локальну об'єкт кулі, який працює майже так само, як і серверний, лише різниця полягає в спрайті.

Це означає, що хоч бачна куля не є абсолютно точним поданням її на сервері, будь-яка різниця буде ледь помітна, якщо вона взагалі є гравцем, а вигода від мережі переважає будь-які невідповідності.

Зверніть увагу на різні методи

Деякі ігри, включаючи мою власну, переміщують кулі за кожним галочкою так, ніби вони є фізичними предметами, тоді як інші просто створюють вектор у напрямку стрільби, або обчислюють весь шлях кулі у створеному галочкою, наприклад, у Counter- Страйкові ігри. Існує кілька маленьких хитрощів, які замальовані на стороні клієнта, наприклад, анімація стрільби з кулі, але для всіх намірів і цілей кожна куля є лише лазером .

У 3D-моделях, які можуть мати складні скриньки, звичайно тестувати зіткнення проти простої обмежувальної коробки ПЕРШИМИ, і якщо це вдасться, перейдіть до більш «детального» виявлення зіткнень.


0

Це називається виявленням зіткнення. 8-бітні комп’ютери робили це за допомогою програмно-ракетної графіки в апаратному забезпеченні. Сучасні ігрові двигуни використовують двигуни фізики та лінійну алгебру. Поточний напрям зброї представлений у вигляді 3D-вектора. Це забезпечує нескінченну лінію в напрямку вогню. Кожен об'єкт, що рухається, має одну або більше обмежувальних сфер, оскільки це найпростіший об'єкт для виявлення зіткнення з лінією. Якщо два перетинаються, це хіт, якщо ні, то не буде потрапляння. Але декорація може бути в дорозі, тому це також слід перевірити (використовуючи обмеження в ієрархічних томах). Найближчий об’єкт, що має перехрестя, - той, що потрапив.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.