Wie gehe ich in einem komponentenbasierten Spiel richtig mit Kollisionen um?


11

Ich versuche, mich mit den Möglichkeiten zu beschäftigen, wie ich mit Kollisionen in einem Spiel um Komponenten richtig umgehen kann.

Ich sehe, dass viele Beispiele PhysicsComponentin die Liste der Entitäten aufgenommen wurden, aber die tatsächliche Implementierung verwirrt mich.

Damit dies funktioniert, PhysicsComponentmüssten sie Zugang zur Welt um sie herum haben. Das ergibt für mich keinen intuitiven Sinn. Sollte eine Komponente nicht nur ihren Container (die Entität), sondern auch den Container ihres Containers (die Welt) nicht kennen?

Für mich klingt es so, als ob das Level oder die Szene eine Liste dieser Entitäten führen sollte und jedes Spielupdate die Entitäten durchlaufen sollte, um festzustellen, welche kollidieren.

Meine Frage ist erstens, ob dies ein gutes Design ist oder nicht, und zweitens, wie zu bestimmen ist, welche Entitäten kollidieren können. Ich nehme an, feste Entitäten könnten eine leere IRigidBody-Schnittstelle implementieren, damit die Ebene bestimmen kann, welche Entitäten in der Liste eine Kollision unterstützen. Aber bricht dies das Komponentendesign?

Sollten sie stattdessen eine leere RigidBody-Komponente enthalten? Dies ist möglicherweise sogar besser, da es möglicherweise nicht immer leer ist und dieser Ansatz zukunftssicherer ist. Das einzige Problem dabei ist die Komplexität. Die Szene müsste nicht nur jede Entität, sondern auch die Komponenten jeder Entität durchlaufen, um festzustellen, ob diese RigidBody-Komponente vorhanden ist.

Drittens sollten beide Entitäten, wenn sie kollidieren, auf irgendeine Weise informiert werden, und ich bin mir nicht sicher, wie dies erreicht werden kann.

Nehmen wir an, dass beide Entitäten eine HealthComponent enthielten und wenn sie kollidierten, ihre Integrität um einen willkürlichen Wert abnahm.

Aber ist dann die Szene für zu viel verantwortlich? Ich könnte sehen, dass dies möglicherweise außer Kontrolle gerät und unhandlich wird, wenn die Szene für viele Dinge verantwortlich ist, zu denen Entitäten keinen (?) Zugang haben sollten.

Bearbeiten: Frage mit mehr Details aktualisiert.


4
Diese Antwort scheint angemessen zu sein, um einen Link zu folgender Adresse
Andrew Russell

Andrews verknüpfte Antwort, James 'Antwort und Nick Wiggills Antwort verdienen alle +1. Stellen Sie sich Komponenten eher als Daten als als eine typische Klasse mit Daten und Methoden vor (nicht, dass sie keine Methoden haben, aber ihnen sollte nicht viel Verantwortung übertragen werden). Schauen Sie sich das Artemis-Komponentensystem ( piemaster.net/2011/07/entity-component-artemis ) an, um ein Beispiel für ein gutes Komponenten-Framework zu finden.
michael.bartnett

Antworten:


5

Ehrlich gesagt, von der Seite des Komponentendesigns her wissen meine Komponenten nichts voneinander, es sei denn, sie müssen es (und das ist sehr selten). Selbst dann bevorzuge ich normalerweise, dass die Komponenten mit einem Verwaltungssystem dieser Komponenten anstelle der Komponenten direkt sprechen. (Die Scripting-Oberfläche sieht aus wie von Objekt zu Objekt, ist jedoch nicht in der tatsächlichen Engine enthalten, hehe).

Zu diesem Zweck würde ich mich an Ihre erste Aussage halten und mich mit Physikkomponenten befassen, die überall dort existieren, wo Objekte auf ihre Kollision getestet werden müssen. Natürlich müssen diese Objekte bei der Lösung von Kollisionen andere Komponenten über sich selbst informieren. Wie bereits erwähnt, ist es mir jedoch lieber, wenn das Ereignis selbst über eine andere Schnittstelle an die Objekte gesendet wird (entweder an einen Manager oder über ein Ereignismeldesystem, wenn Sie haben zum Beispiel eine davon).

Ich denke, Sie sind auf dem richtigen Weg und brauchen einfach mehr von einem "Ja, das klingt richtig". Also ... Ja, das klingt richtig.

Hoffe das hilft!


3

Normalerweise verwenden Game Engines eine Bibliothek von Drittanbietern, um Kollisionen zwischen Entitäten zu erkennen. In diesem Szenario werden diejenigen Entitäten erstellt oder registriert, die die PhysicsComponent in der "Physik" -Welt haben. Und wenn es eine Kollision zwischen zwei Entitäten (A und B) feststellt, ruft es normalerweise einen Rückruf an die Entität A auf und informiert, dass sie mit der Entität B kollidiert ist, und dasselbe für die Entität B und informiert, dass sie mit der Entität A kollidiert ist.

Für 2D ist Box2D eine bekannte freie Physikbibliothek. Auch ein Blick auf Chipmunk lohnt sich. Für 3D ist Bullet kostenlos (wahrscheinlich das beste kostenlose, das Sie finden können). Havok und PhysX sind dafür bekannt, in vielen Triple-A-Spielen verwendet zu werden.


2

Das Problem, das Sie haben, besteht darin, dass die Kollisionserkennung (der einzige Grund, warum Sie eine physikalisch-komponententragende Entität benötigen, um auf eine andere zu verweisen) auf einer höheren Ebene durchgeführt wird, normalerweise entweder direkt von Ihrer Spieleschleife oder von eine Hilfsfunktion / Klasse, die dies tut. Meine Antwort vor einigen Wochen an jemanden bezieht sich auf die Entfernung von Entitäten aus ähnlichen Gründen, und wenn Sie bedenken, dass bei einer Kollision eine Ihrer Entitäten zerstört wird, ist dieselbe Antwort in ihrem gegebenen Kontext für Sie von großer Relevanz , da eine "höhere Macht" noch die Aufräumarbeiten an den Körpern erledigen muss ... sozusagen.

Dies alles nur zwischen Unternehmen zu tun, ist im Allgemeinen nicht praktikabel. In einer soliden Architektur gibt es fast immer einen Proxy für solche Dinge, sei es über direktes Management wie bei der Kollisionserkennung oder über Ereignisaussendungen wie z. Ein Player-Messaging-System, bei dem ein clientseitiger Messaging-Manager die von Playern gesendeten Nachrichten abhört und an den Server weiterleitet, um sie an alle weiterzuleiten.


2

Ich stehe jetzt genau vor dem gleichen Problem wie Sie in einem Projekt. Die Art und Weise, wie ich mich dazu entschlossen habe, ist eine "ColliderComponent", die den Körper von der Physik-Engine fernhält. Die Körper werden extern definiert (Formdefinitionen, die zur Laufzeit geladen werden) und dann der Physikwelt und den Spieleinheiten, zu denen sie gehören, hinzugefügt .

Ich verwende Box2D, wo Sie einen "Kollisions-Listener" anhängen können, der durch die Kollision benachrichtigt wird. Da ich einen Zeiger auf meine "ColliderComponent" zu den Benutzerdaten des Körpers hinzufüge, kann ich meine zwei ColliderComponents abrufen, die Teil der Kollision waren.

Wenn also eine Kollision auftritt, geschieht Folgendes: Die ColliderComponents, die Teil der Kollision waren, senden eine Nachricht an ihr Eigentümerobjekt (die Spieleinheit), die diese Nachricht wiederum an alle ihre Komponenten sendet.

Jede Komponente kann dann auf diese Nachricht reagieren, sodass Ihre "Gesundheitskomponente" 5 Punkte aus der Gesundheit usw. entfernen kann.


+1: Ich benutze einen sehr ähnlichen Ansatz. Wie bestimmen Sie die Höhe des zu verursachenden Schadens in Abhängigkeit von der Art der kollidierenden Einheiten?
Den

@Den Ich sende je nach der aufgetretenen Kollision verschiedene Nachrichten (oder Nachrichtendaten). Dies funktioniert gut für mich, da ich nicht viele verschiedene Fälle zu behandeln habe.
Mistzack

0

Erstellen Sie ein Kollisionssystem, das die Kollisions- "Welt" kennt. Dann weisen Sie in Ihrer Kollisionskomponente das Kollisionssystem an, einen Strahl von Punkt A nach B zu werfen und zu antworten, ob er kollidiert ist oder nicht.

Viel Glück. Ich finde das Kollisionssystem eines der langweiligeren Teile der Spiel-Engine.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.