Как правильно обрабатывать столкновения в компонентной игре?


11

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

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

Для того, чтобы это работало, PhysicsComponentнеобходим доступ к окружающему миру. Это не имеет смысла для меня. Разве компонент не должен знать не только о своем контейнере (объекте), но и контейнере своего контейнера (мир)?

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

Мой вопрос, во-первых, хороший ли это дизайн или, во-вторых, как определить, какие объекты могут сталкиваться. Я предполагаю, что твердые объекты могут реализовать пустой интерфейс IRigidBody, чтобы уровень мог определить, какие объекты в списке поддерживают коллизию. Но это нарушает дизайн компонентов?

Вместо этого они должны содержать пустой компонент RigidBody? На самом деле это может быть лучше, потому что он не всегда может быть пустым, и этот подход более ориентирован на будущее. Единственная проблема с этим - сложность. Сцена должна была бы проходить не только по каждой сущности, но и по компонентам каждой сущности, чтобы определить, есть ли у нее этот компонент RigidBody.

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

Предположим, что обе сущности содержат HealthComponent, и когда они сталкиваются, их здоровье будет уменьшено на какое-то произвольное значение, 5. Я полагаю, что сцена должна будет справиться с этим, когда обнаружит коллизию между двумя сущностями?

Но тогда сцена несет ответственность за слишком много? Я мог видеть, что это может выйти из-под контроля и стать громоздким, когда сцена ответственна за многие вещи, к которым сущности не должны (?) Иметь доступ.

Изменить: Вопрос обновлен с более подробной информацией.


4
Этот ответ кажется подходящим для ссылки на: gamedev.stackexchange.com/questions/13797/…
Эндрю Рассел

Связанный ответ Эндрю, ответ Джеймса и ответ Ника Виггилла заслуживают +1. Думайте о компонентах как о данных, а не как о типичном классе с данными и методами (не то, чтобы у них не было методов, но им не следует давать большую ответственность). Посмотрите на систему компонентов Artemis ( piemaster.net/2011/07/entity-component-artemis ) для примера хорошей структуры компонентов.
Майкл Бартнетт

Ответы:


5

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

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

Я думаю, что вы на правильном пути и вам просто нужно больше «Да, это звучит правильно». Итак ... Да, это звучит правильно.

Надеюсь это поможет!


3

Обычно игровые движки используют стороннюю библиотеку для обнаружения коллизий между сущностями. В этом сценарии можно создать или зарегистрировать те объекты, у которых есть физический компонент, в «физическом» мире. И всякий раз, когда он обнаруживает коллизию между двумя объектами (A и B), он обычно вызывает обратный вызов для объекта A, сообщая, что он столкнулся с объектом B, и то же самое для объекта B, сообщая, что он сталкивался с объектом A.

Для 2D хорошо известная бесплатная физическая библиотека - Box2D. Также стоит взглянуть на Бурундука. Для 3D Bullet бесплатна (вероятно, лучшая бесплатная, которую вы можете найти). Havok и PhysX известны тем, что их используют во многих тройных играх.


2

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

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


2

У меня сейчас точно такая же проблема, как и у вас в проекте. Я решил заняться этим, имея «ColliderComponent», который удерживает тело от физического движка. Тела определяются внешне (определения формы, которые загружаются во время выполнения), а затем добавляются в физический мир и игровые сущности, к которым они принадлежат.

Я использую Box2D, где вы можете подключить «слушатель столкновений», который будет получать уведомления при столкновении. Поскольку я добавляю указатель на мой «ColliderComponent» к пользовательским данным bodys, я могу получить два моих ColliderComponent, которые были частью столкновения.

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

Каждый компонент может затем отреагировать на это сообщение, так что ваш «компонент здоровья» может убрать 5 очков здоровья и т. Д.


+1: я использую очень похожий подход. Как вы определяете размер ущерба в зависимости от типа столкнувшихся объектов?
День

@ Я отправляю разные сообщения (или данные сообщения) в соответствии с произошедшим столкновением. Это хорошо работает для меня, так как у меня нет много разных дел для обработки.
Bummzack

0

Создайте систему столкновений, которая знает столкновение "мир". Затем в вашем компоненте столкновения скажите системе столкновений, что нужно направить луч из точки A в B и ответить, столкнулся он или нет.

Удачи. Я считаю систему столкновений одной из самых утомительных частей игрового движка.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.