Як працює двигун зіткнення?


78

Як саме працює двигун зіткнення ?

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

Якщо ви не знаєте, що таке двигун зіткнення, він, як правило, використовується в платформних іграх для того, щоб гравець гостро вдарив об стіни тощо. Є 2D і 3D тип, але всі вони досягають одного й того ж: зіткнення.

Отже, що тримає двигун зіткнення?


3
Можна обманювати з обмежувальними коробками та сферами, перетин яких швидко визначити. Тоді ви можете більш уважно оглянути. cs.unc.edu/~dm/collision.html en.wikipedia.org/wiki/Collision_detection Ви завжди можете це робити повільно за допомогою наївного алгоритму. Comp Geometry має кілька хитрощів, які використовують перевагу геометричного характеру проблеми та роблять алгоритм швидшим. Ось дуже хороший документ: cs.hku.hk/research/techreps/document/TR-2005-01.pdf

що таке двигун зіткнення ?

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

Відповіді:


172

Існує велика різниця між двигуном зіткнення та двигуном фізики. Вони не роблять те саме, хоча двигун фізики, як правило, покладається на двигун зіткнення.

Потім двигун зіткнення розбивається на дві частини: виявлення зіткнення та реакцію на зіткнення. Останній, як правило, є частиною фізичного двигуна. Ось чому двигуни зіткнення і фізичні двигуни зазвичай згортаються в одну бібліотеку.

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

Виявлення зіткнення

Виявлення зіткнення відносно легко. Кожен об’єкт має перетворення та форму (можливо, декілька фігур). Наївні підходи повинні змусити двигун зіткнення зробити цикл O (n ^ 2) через всю об'єктну пару і випробувати, якщо між парами накладеться перекриття. У розумніших підходах є кілька просторових структур даних (наприклад, для статичних та динамічних об'єктів), обмежуюча форма для кожного об'єкта та багаточастинні опуклі підформи для кожного об'єкта.

Структури просторових даних включають такі речі, як KD-Дерева, динамічні дерева AABB, Octrees / Quadtrees, Binary Space Partitioning дерева тощо. У кожного є свої переваги та недоліки, тому деякі двигуни вищого класу використовують більше одного. Наприклад, динамічні дерева AABB дійсно дуже швидкі і хороші для обробки безлічі рухомих об'єктів, тоді як KD-дерево може бути більш придатним для геометричної статичної рівня, з якою стикаються об'єкти. Є й інші варіанти.

Широка фаза використовує структури просторових даних та абстрактний обмежуючий обсяг для кожного об'єкта. Обмежуючий об'єм - це проста форма, яка охоплює весь об'єкт, як правило, з метою закріпити його максимально "щільно", залишаючись дешевим, щоб зробити тести зіткнення. Найпоширеніші обмежувальні форми - це осеві вирівнювання, орієнтовані на осі, об'ємно-орієнтовані обмежувальні коробки, сфери та капсули. AABBs, як правило, вважаються найшвидшими та найпростішими (сфери в деяких випадках простіші та швидші, але для багатьох таких просторових структур даних все-таки знадобиться перетворення сфери в AABB), але вони також мають тенденцію досить погано вміщувати багато об'єктів. Капсули популярні в 3D-двигунах для управління зіткненнями на рівні персонажів. Деякі двигуни будуть використовувати дві обмежуючі форми,

Остання фаза виявлення зіткнення - це виявлення, де саме перетинається геометрія. Зазвичай це передбачає використання сітки (або багатокутника в 2D), хоча не завжди. Мета цього етапу - з’ясувати, чи справді об'єкти справді стикаються, чи потрібен тонкий рівень деталізації (скажімо, зіткнення кулі в стрільці, де ви хочете ігнорувати постріли, які ледь не пропускають), і також з’ясувати, де саме стикаються об’єкти, що впливатиме на те, як реагують об’єкти. Наприклад, якщо ящик сидить на краю столу, двигун повинен знати, в яких моментах стіл притискається до коробки; залежно від того, наскільки далеко висить ящик, коробка може почати нахилятися і опадати.

Контактний генератор

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

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

Фізична реакція

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

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

Більш просунута фізична реакція швидко ускладнюється. Підхід, описаний вище, руйнується у багатьох ситуаціях, включаючи один об'єкт, що сидить поверх двох інших. Зв'язок з кожною парою сам по собі викличе «тремтіння», і об’єкти будуть багато підстрибувати. Найбільш основний прийом - це зробити ряд ітерацій корекції швидкості над парами об'єктів, що стикаються. Наприклад, з коробкою "А", що сидить поверх двох інших коробок "В" і "С", зіткнення AB спочатку буде оброблятися, внаслідок чого коробка A буде нахилятися далі в коробку C. Потім відбувається зіткнення змінного струму, ввечері вийміть коробки трохи, але потягнувши A вниз і B. Потім робиться ще одна ітерація, тому помилка AB, викликана корекцією змінного струму, трохи усувається, створюючи трохи більше помилок у відповіді змінного струму. Що обробляється при повторній обробці змінного струму. Кількість виконаних ітерацій не визначена, і немає сенсу, коли він стає «ідеальним», а навпаки, будь-яка кількість ітерацій не припиняє давати значущих результатів. 10 ітерацій є типовою першою спробою, але потрібно налаштувати, щоб визначити найкраще число для певного двигуна та певної потреби гри.

Зверніться до кешування

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

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

Сплячий

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

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

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

Обмеження

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

Навіть основи вирішення обмежень можуть бути дуже інтенсивними з математики і виходять за рамки мого досвіду в цій темі. Рекомендую ознайомитись із чудовою серією статей з фізики Ренді Гаула для більш поглибленого пояснення теми.


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

1
@ gardian06: це огляд, що швидко пишеться, впевнений, що його можна було б трохи розширити. Наприклад, я забув згадати об'єкт сну, наприклад, що дуже корисно. для ітерацій я повторюю всі колекції пар, і навіть при відносно великій кількості ітерацій (20+) я ніколи не помічав проблеми з продуктивністю (але знову ж таки, це з сплячим об'єктом, тому порівняно невелика кількість активних зіткнень вирішити ).
Шон Міддлічч

1
Фантастична відповідь, +1. Читаючи це, дійсно змушує мене реалізувати ці алгоритми.
Майлз Рут

3

Загальна проблема: визначте, яка з усіх можливих комбінацій об'єктів має ненульовий пересічний об'єм.

Наївний, загальний підхід простий: для кожної можливої ​​пари об'єктів обчисліть об'єм пересічення. Зазвичай це не практично, оскільки вимагає O (n ^ 2) відносно дорогих операцій пересічення.

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


2

Один "двигун зіткнення", який я використав, відчував надзвичайно легко.

В основному, API надав вид об'єктів, що мають метод collidesWith, такий, що

  1. його параметри були різними видами об'єктів, які «підлягали» зіткненню
  2. вона поверталася справжньою чи хибною залежно від того, сталося зіткнення чи ні
  3. з'явилася опція, що дозволяє вибрати, чи всі обмежуючі прямокутники для об'єктів викликають зіткнення події або лише непрозорі пікселі в цих прямокутниках (виявлення рівня пікселів)

У своїй заяві я просто періодично звертався, collidesWithщоб з’ясувати, сталося зіткнення чи ні.

Досить просто, чи не так?


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

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

  • Кінцевим користувачам просто байдуже, скільки об’єктів знаходиться за сценою. Вони щасливі, поки кінцевий результат відчувається так, як вони очікують, наприклад, як будинок із огорожею заднього двору:

    http://i.stack.imgur.com/4Wn5B.jpg


2

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

можливість сказати, що цей елемент переміщено з місця X у місце Y, засноване на фізиці (це також атакує, як вони рухаються, і чому вони рухаються)

метод, який використовується для виявлення зіткнень, визначається на основі структури вашої гри. якщо у вашій грі великий відкритий світ, вам слід дуже врахувати розділення простору (квадратичне дерево [oct-tree для 3D], BSP, традиційна сітка або старомодний тест на все, що підходить)

найкращий спосіб впровадження системи виявлення зіткнень - це робити поетапно.

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

  2. якщо 1 пройшов, то повторіть із складнішим об’ємом / формою повторіть до готовності перевірити абсолютну геометрію

  3. перевірити абсолютну геометрію, скільки разів ви повторите крок 2, слід визначити, залежно від складності ваших фігур та наскільки точними вони є.

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

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

традиційний цикл виглядає так:

receive input
update physics
collision detection
collision resolution
render
repeat

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

Більшість ігрових двигунів випробовують абсолютну геометрію у багатьох (не у всіх) випадках. Без цього будуть дуже очевидні «провали» у відповіді фізики. Більшість двигунів матимуть просту широку фазу (просторовий розподіл), простий тест обмеження обсягу (найчастіше AABB), а потім (при необхідності) тест спрощеної геометрії (наприклад, не та ж геометрія, як геометрія повного LOD візуалізації, але ще необроблена геометрія, яка, ймовірно, є однією з низьких версій LOD виведеної сітки).
Шон Міддлічч

@seanmiddleditch, що більше моїм наміром було те, що наближення буде перевірено, як правило, намагаючись уникнути тестування увігнутого багатокутника / багатогранника.
gardian06

@ktodisco це залежить від увігнутості фігури, і наскільки вона повинна бути точною, а потім, що потрібно повернути фізичній системі для вирішення зіткнення, оскільки це може змінюватися залежно від двигуна фізики та передбачуваної точності відповідь
gardian06

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

1

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

Див. BSP та Kd дерева для отримання додаткової інформації. Існують також інші підходи до розподілу.


0

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

По-друге, але також важливо, перевірити більш детально (точно) по відношенню до решти об'єктів, які не були вибиті на цьому першому кроці.

По-третє, використовувати найефективніші / відповідні методи для проведення перевірок.

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