Mehr Spaß mit einem ES ...
Derzeit habe ich ein paar Systeme:
- Renderer (Attribut "Renderbar", Attribut "Transformieren")
- Bewegung (Attribut "Verschiebbar", Attribut "Transformieren", Attribut "Renderbar" [für Begrenzungsrahmen usw.])
- Eingabe (InputReceiver-Attribut)
- etc.
Ich füge die Kollisionserkennung hinzu. Mein erster Gedanke war, ein neues System hinzuzufügen, das Kollisionen ausführt. Es macht Sinn für mich diese aus dem isoliert zu halten Motion
System aller Dinge , da sie nicht bewegen oder notwendigerweise in Kollisionserkennung teilnehmen animiert - Kameras, Nebel, etc. - aber es scheint , dass Collision
und Motion
voneinander abhängig sind.
Wenn Motion
ein Objekt bewegt wird, muss die Transformation mit validiert Collision
und die Bewegung entweder abgebrochen oder angepasst werden (Prellen, Anhalten an einer Wand usw.).
Eine Alternative wäre, ein Collidable-Attribut zu erstellen, das einen Verweis auf ein Kollisionsobjekt - kd-tree, octree usw. - verwaltet, das von Entitäten gemeinsam genutzt wird, die miteinander kollidieren können. Das Motion
System würde dann nach diesem Attribut suchen und es verwenden, um die Bewegung zu überprüfen oder anzupassen.
Aus Code-Sicht ist das eine akzeptable Lösung. Aus Sicht der ECS-Architektur scheint es jedoch so zu sein, dass Logik in das Motion
System hineingeschoben wird, die nicht für alle Entitäten gilt, die ein Movable
Attribut haben.
Ich könnte auch einen Bewegungsvektor in dem Movable
Attribut speichern und das Collider
System Transform
nach Bedarf anpassen lassen , aber dazu gehört das Duplizieren von Funktionen zwischen Motion
und Collider
oder ein Rückruf von Collider
bis Motion
mit einigen Daten über den Kollisionsort und Oberflächendaten für Abprall / Reflexion usw .
Dies mag unter die Überschrift "Special Case Hack" fallen, aber ich möchte einige Eingaben von denen erhalten, die dies zuvor behandelt haben, ohne eine Tonne Edge-Case-Code zu erstellen.
Die Frage Was ist ein guter Weg, um eine enge Kopplung zwischen Bewegungs- und Kollisionssystemen zu vermeiden, wenn sie scheinbar voneinander Kenntnis benötigen?
Antworten:
Sie überdenken es. In meiner Engine, die auch ein Entity-Component-System verwendet,
GameObject
kann jeder einen Zeiger auf a habenModuleCollision
.Was passiert, wenn das Spiel aktualisiert wird:
Update
Funktion für jeden aufGameObject
.Update
Funktion aktualisiert jederGameObject
nur seine Geschwindigkeit und Richtung, nicht seine Position.GameObject
lädt seine aktuelle Position, Geschwindigkeit und Richtung hochModuleCollision
, falls verfügbar.ModuleCollision
Basis durch.UpdatePost
Funktion aufGameObject
. Wenn das Objekt ein Kollisionsmodul hat, ruft es die aktualisierte Position, Geschwindigkeit und Richtung vom Kollisionsmodul ab. Die Position wird mit der Geschwindigkeit und Richtung aktualisiert.GameObject
Konstrukt erstellt eine endgültige 3x3-Matrix aus seiner Position und Überschrift.Ja, es gibt einige Überschneidungen, aber das ist in Ordnung. Das Kollisionshandling auf a
ModuleCollision
ist der beste Weg, um dies zu tun , da Sie sonst prüfen müsstenGameObject
, ob es einenModuleCollision
Handle hat.quelle
Ich würde es so machen ...
Habe drei Systeme:
Das Bewegungssystem wendet Geschwindigkeiten auf Positionen an. Das Beschleunigungssystem übt Kräfte auf Geschwindigkeiten aus. Das Kollisionssystem erkennt Kollisionen und wendet die Kräfte in die richtigen Richtungen an. Wenn Sie grobe Kollisionen wünschen, werden die Geschwindigkeiten direkt geändert.
Sie können beispielsweise den Winkel zwischen den Kollisionen mit atan2 berechnen und dann verwenden, um die richtigen Kräfte / Geschwindigkeiten auf die Körper anzuwenden.
Lassen Sie das Kollisionserkennungssystem bei Bedarf auch Nachrichten senden.
quelle