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?
Antworten:
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:
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.
quelle
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()
undOnCollisionExit()
, 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.
quelle
OnTriggerEnter()
undOnTriggerExit()
, oder?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.
quelle