Wie soll ich das feindliche Bewusstsein der Einheiten implementieren?

12

Ich benutze Unity3d, um einen RTS / TD-Hybrid-Prototyp zu entwickeln. Was ist der beste Ansatz für das "Bewusstsein" zwischen Einheiten und ihren Feinden? Ist es vernünftig, wenn jede Einheit den Abstand zu jedem Feind überprüft und sich in Reichweite befindet?

Der Ansatz, den ich jetzt verfolge, ist, auf jeder Einheit eine Triggerkugel zu haben. Wenn ein Feind den Abzug drückt, wird die Einheit auf den Feind aufmerksam und beginnt mit der Entfernungsprüfung. Spart dies unnötige Überprüfungen?

Was ist die beste Vorgehensweise hier?

Phil
quelle
Ich sollte hinzufügen, dass die Anzahl der Einheiten / Feinde in der Größenordnung des Oberbefehlshabers liegen wird
Phil

Antworten:

10

Betrachten Sie die Bounding Volume Hierarchies (BVH). Sie werden am häufigsten bei der Kollisionserkennung verwendet, um die Anzahl der Überprüfungen zu verringern, die bei der Berechnung von Kollisionen erforderlich sind, oder beim Rendern, um das Ausmerzen von Objekten zu verhindern. Da Sie bereits Kugeln verwenden, würde ich einen Kugelbaum vorschlagen , obwohl andere Volumes wie AABBs möglicherweise effizienter sind. Ich bin mir nicht sicher, welche Unterstützung Unity für solche Dinge hat, wie ich sie noch nie benutzt habe, aber wahrscheinlich gibt es bereits etwas in der Kollisionserkennung oder in der Wiedergabe von Teilen der Engine.

Grundsätzlich möchten Sie Gegner, die sich in der Nähe befinden, in mehrere übergeordnete Bereiche gruppieren. Wenn eine Einheit bewegt wird, überprüfen Sie die Auslösekugel gegen die übergeordnete Kugel, anstatt jeden Feind zu überprüfen. Wenn sich die Triggerkugel mit der übergeordneten Kugel schneidet, überprüfen Sie jeden Feind innerhalb. Wenn dies nicht der Fall ist, können Sie alle darin enthaltenen Feinde ablegen. Sie möchten mehrere Kugelebenen basierend auf der maximalen Kugelgröße oder der Anzahl der Gegner für jede Kugel einrichten und die Prüfung basierend auf einer Kugel der obersten Ebene durchführen. Dann müssen Sie nur noch den Baum hinuntergehen, um jeden Feind zu überprüfen, ohne die Entfernungsprüfung für jeden einzelnen durchführen zu müssen.

Erforderliche Schritte für jeden Frame:

  1. Bewegen Sie Feinde
  2. Baue die BVH neu auf / aktualisiere sie für neue feindliche Positionen
  3. Einheiten bewegen und gegen Kugelbaum prüfen.

Dies kann die Überprüfungen reduzieren, die bei vielen Feinden erforderlich sind, aber der Aufwand für das Aktualisieren und Speichern des Baums lohnt sich möglicherweise nicht, wenn nicht so viele vorhanden sind. Ich kenne Supreme Commander nicht, um zu wissen, wonach Sie suchen, also gehe ich nur von "Hunderten" aus. Sie müssen sich in verschiedenen Situationen profilieren, um herauszufinden, ob sich der Aufwand für Sie lohnt.

Joel Baker
quelle
3
+1 Dieser Ansatz ist am einfachsten, obwohl er einige Fehler aufweist. OP möchte dies möglicherweise implementieren und dann so etwas wie einen Octree implementieren. Außerdem reagieren die Einheiten in den meisten RTS mit einer gewissen Verzögerung. Tatsächlich wird die meiste KI in Spielen mit 10-30 Bildern pro Sekunde berechnet, wobei das Spiel mit 30-60 Bildern pro Sekunde laufen kann (die Zahlen sind natürlich Näherungswerte).
Samaursa
Danke, das war genau das, was ich brauchte, um noch einen Schritt weiter zu gehen. Ich werde nachsehen, wie BVH in Unity implementiert wird. Sehr pädagogischer und informativer Beitrag! +1
Phil
Oh und sehen Sie sich Supreme Commander an, wenn Sie bei RTS sind. Es ist in der Tat ein sehr schönes Spiel, genau wie alle Chris Taylor-Spiele.
Phil
7

Es ist nicht erforderlich, BVHs zu implementieren, da die Kollisions-Engine von Unity dies im Wesentlichen bereits für Sie erledigt.

Befestigen Sie einfach einen großen Bounding-Sphere-Trigger an jeder Einheit (der deren Reichweite darstellt) und behandeln Sie die Rückrufe OnCollisionEnter()und OnCollisionExit(), um zu verfolgen, welche Feinde sich in Reichweite jeder Einheit befinden.

Beachten Sie, dass Sie interessiert sind, wenn eine andere Einheit mit der Kugel kollidiert und nicht, wenn die Kugel einer anderen Einheit mit der Kugel kollidiert.

BlueRaja - Danny Pflughoeft
quelle
1
Ich denke, dies muss zumindest knapp über der akzeptierten Antwort bewertet werden. Die akzeptierte Antwort ist gut zum Lernen, aber diese Antwort sollte ganz oben stehen, da dies der praktischste Weg ist.
Varaquilex
Ich glaube du meinst OnTriggerEnter()und OnTriggerExit(), oder?
Jibb Smart
1

Eine andere Lösung, die sich sehr gut skalieren lässt und für eine Vielzahl anderer Dinge verwendet werden kann, ist eine Einflusskarte. Generieren Sie eine Reihe von Rasterfeldern um die Einheit, um innerhalb des X-Radius zu scannen. Durchsuche diese Kacheln nach einem Feind, der auf einem von ihnen steht. Wenn Sie die nächsten Feinde haben möchten, können Sie Ihr Set nach Entfernung sortieren.

Dies ist möglicherweise die effizienteste Methode, insbesondere wenn Sie andere Aufgaben mit Einfluss auf die Karte ausführen möchten, z. B. Nebel des Krieges oder Wegfindung.

Hier ist ein Video, in dem ich das Konzept erklärt habe: https://www.youtube.com/watch?v=MEd6XV2Pecw .

Und hier ist eine Implementierung: https://www.youtube.com/watch?v=y_ewoxlZlgc

Ich empfehle, die Einheitensammlung des Rasterfelds nicht beim Start zu initialisieren, sondern nur dann, wenn die Sammlung benötigt wird.

Alternativ können Sie ein Array mit X-Länge verwenden, wenn Sie wissen, dass eine Kachel niemals mehr als X-Einheiten enthält.

JPtheK9
quelle