Як правильно впоратися зіткненням у грі на основі компонентів?


11

Намагаюся обернути голову навколо способів правильно впоратися зіткненням у грі, розробленій навколо компонентів.

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

Щоб це працювало, PhysicsComponentпотрібен був би доступ до навколишнього світу. Це не має для мене інтуїтивного сенсу. Чи не повинен компонент не знати про свій контейнер (сутність), але і про його контейнер (світ)?

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

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

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

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

Скажімо, що обидві організації містили HealthComponent, і коли вони зіткнулися, то їхнє здоров'я зменшилось би на деяку довільну цінність 5. Я гадаю, що відповідальність за цю ситуацію повинна виявити, коли виявить зіткнення двох об'єктів?

Але тоді сцена занадто велика? Я міг бачити, як це може вийти з рук і стати непростим, коли сцена відповідає за багато речей, до яких суб'єкти не повинні (?) Мати доступ.

Редагувати: запитання оновлено з більш детальною інформацією.


4
Ця відповідь здається доречною для посилання на: gamedev.stackexchange.com/questions/13797/…
Ендрю Рассел

Пов'язана відповідь Ендрю, відповідь Джеймса та відповідь Ніка Віггілла заслуговують +1. Розглядайте компоненти більше як дані, ніж як типовий клас із даними та методами (не те, що у них не буде методів, але за них не слід нести велику відповідальність). Подивіться на систему компонентів Artemis ( piemaster.net/2011/07/entity-component-artemis ) для прикладу гарної компоненти компонентів.
michael.bartnett

Відповіді:


5

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

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

Я думаю, що ти на вірному шляху і просто потрібно більше "Так, це звучить правильно" Так .. Так, це звучить правильно.

Сподіваюся, це допомагає!


3

Зазвичай ігрові двигуни використовують сторонні бібліотеки для виявлення зіткнень між сутностями. У цьому сценарії створюються або реєструються ті сутності, які мають компонент Physics, у світ "фізики". І кожного разу, коли він виявляє зіткнення між двома сутностями (A і B), він зазвичай викликає зворотний виклик суб'єкту A, повідомляючи, що він зіткнувся з суттю B, і той же самий для суб'єкта B, повідомляючи, що він зіткнувся з суттю A.

Для 2D добре відомою бібліотекою безкоштовної фізики є Box2D. Також варто поглянути на бурундука. Для 3D програма Bullet безкоштовна (можливо, найкраща безкоштовна, яку ви можете знайти). Havok і PhysX відомі тим, що використовуються у багатьох потрійних А Іграх.


2

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

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


2

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

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

Тож, що відбувається при зіткненні, наступне: ColliderComponents, які були частиною зіткнення, відправлять повідомлення своєму власнику-об'єкту (грі-об'єкту), який, у свою чергу, передаватиме це повідомлення всім його компонентам.

Кожен компонент може потім реагувати на це повідомлення, тож ваш "компонент здоров'я" міг би зняти 5 балів зі здоров’я тощо.


+1: Я використовую дуже подібний підхід. Як Ви визначаєте суму заподіяної шкоди залежно від типу суб'єктів, що стикаються?
День

@Дені я надсилаю різні повідомлення (або дані повідомлення) відповідно до зіткнення, що сталося. Це добре працює для мене, оскільки я не маю багато різних справ для вирішення.
bummzack

0

Створіть систему зіткнення, яка знає зіткнення «світ». Тоді у своєму компоненті зіткнення скажіть системі зіткнення, щоб кинути промінь від точки А до В і відповісти, зіткнувся він чи ні.

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

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