Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

Optimieren der Navigations-Performance

../../_images/nav_optimization.webp

Häufige Performance-Probleme im Zusammenhang mit der Navigation lassen sich in die folgenden Kategorien einteilen:

  • Performance-Probleme bei der Analyse von Nodes des Szenenbaums für das Backen von Navigations-Meshes.

  • Performance-Probleme beim Backen des eigentlichen Navigations-Meshs.

  • Performance-Probleme mit NavigationAgent-Pfadabfragen.

  • Performance-Probleme bei der eigentlichen Pfadsuche.

  • Performance-Probleme bei der Synchronisierung der Navigations-Map.

In den folgenden Abschnitten finden Sie Informationen darüber, wie Sie deren Auswirkungen auf die Framerate erkennen und beheben oder zumindest abmildern können.

Performance-Probleme beim Parsen von Nodes in Szenenbäumen

Tipp

Verwenden Sie vorzugsweise einfache Formen mit möglichst wenigen Kanten, z. B. keine runden Formen wie Kreise, Kugeln oder Torus.

Bevorzugen Sie physikalische Collision Shapes gegenüber komplexen visuellen Meshes als Ausgangsgeometrie, da Meshes von der GPU kopiert werden müssen und in der Regel viel detaillierter sind als nötig.

Vermeiden Sie im Allgemeinen die Verwendung sehr komplexer Geometrie als Ausgangsgeometrie für das Backen von Navigationsmeshes. Verwenden Sie z.B. niemals ein sehr detailliertes visuelles Mesh, da das Parsen seiner Form in Datenarrays und die Voxelisierung für das Backen des Navigationsmeshs viel Zeit in Anspruch nehmen wird, ohne dass das endgültige Navigationsmesh dadurch an Qualität gewinnt. Verwenden Sie stattdessen eine sehr detailarme Version einer Geometrie. Noch besser ist es, sehr primitive Geometrien wie Kästchen und Rechtecke zu verwenden, die nur grob die gleiche Geometrie abdecken, aber dennoch ein Ergebnis liefern, das gut genug für die Wegfindung ist.

Bevorzugen Sie einfache Physik-Collision Shapes gegenüber visuellen Meshes als Ausgangsgeometrie für das Backen von Navigationsmeshes. Physik-Shapes sind standardmäßig sehr begrenzte und optimierte Geometrien, die einfach und schnell zu analysieren sind. Ein visuelles Mesh hingegen kann von einfach bis komplex reichen. Um Zugriff auf visuelle Mesh-Daten zu erhalten, muss der Parser die Mesh-Daten-Arrays vom RenderingServer anfordern, da visuelle Mesh-Daten direkt auf der GPU gespeichert werden und nicht auf der CPU zwischengespeichert sind. Dies erfordert das Sperren des RenderingServer-Threads und kann die Framerate zur Laufzeit stark beeinträchtigen, wenn das Rendering in mehreren Threads ausgeführt wird. Wenn das Rendering als Single-Thread läuft, kann die Auswirkung auf die Framerate noch schlimmer sein und das Mesh-Parsing kann bei komplexen Meshes das gesamte Spiel für ein paar Sekunden einfrieren.

Performance-Probleme beim Backen von Navigations-Meshes

Tipp

Zur Laufzeit sollte immer ein Hintergrund-Thread für das Backen von Navigations-Meshes verwendet werden.

NavigationMesh cell_size und cell_height erhöhen, um weniger Voxel zu erzeugen.

Ändern Sie den SamplePartitionType von Watershed auf Monotone oder Layers, um die Performance beim Backen zu erhöhen.

Warnung

Skalieren Sie Quellgeometrie NIEMALS mit Nodes, um Präzisionsfehler zu vermeiden. Die meisten Skalierungen gelten nur visuell und Geometrien, die in ihrem Grundmaßstab sehr groß sind, erfordern auch bei einer Verkleinerung noch eine Menge zusätzlicher Bearbeitung.

Das Backen von Navigations-Meshes zur Laufzeit sollte nach Möglichkeit immer in einem Hintergrund-Thread erfolgen. Selbst kleine Meshes können weitaus mehr Zeit in Anspruch nehmen, als man in ein einzelnes Frame quetschen kann, zumindest wenn die Framerate auf einem erträglichen Niveau bleiben soll.

Complexity of source geometry data parsed from scene tree nodes has big impact on baking performance as everything needs to be mapped to a grid / voxels. For runtime baking performance the NavigationMesh cell size and cell height should be set as high as possible without causing navigation mesh quality problems for a game. If cell size or cell height is set too low the baking is forced to create an excessive amount of voxels to process the source geometry. If the source geometry spans over a very large game world it is even possible that the baking process runs out of memory in the middle and crashes the game. The partition type can also be lowered depending on how complex the games source geometry is to gain some performance. E.g. games with mostly flat surfaces with blocky geometry can get away with the monotone or layers mode that are a lot faster to bake (e.g. because they require no distance field pass).

Skalieren Sie niemals die Quellgeometrie mit Nodes. Dies kann nicht nur zu vielen Präzisionsfehlern mit falsch angepassten Vertices und Kanten führen, sondern auch dazu, dass manche Skalierungen nur visuell und nicht in den tatsächlich geparsten Daten vorhanden sind. Wenn z.B. ein Mesh im Editor visuell herunterskaliert wird, z.B. die Skalierung auf 0.001 bei einer MeshInstance, benötigt das Mesh immer noch ein gigantisches und sehr komplexes Voxel-Gitter, um für das Baking verarbeitet zu werden.

Performance-Probleme mit NavigationAgent-Pfadabfragen

Tipp

Vermeiden Sie unnötige Pfadrücksetzungen und Abfragen bei jedem Frame in NavigationAgent-Skripten.

Vermeiden Sie es, alle NavigationAgent-Pfade im selben Frame zu aktualisieren.

Logische Fehler und verschwenderische Operationen in den benutzerdefinierten NavigationAgent-Skripten sind sehr häufige Ursachen für Performance-Probleme, z.B. das Zurücksetzen des Pfades in jedem einzelnen Frame. Standardmäßig sind NavigationAgents so optimiert, dass sie nur dann neue Pfade abfragen, wenn sich die Zielposition ändert, die Navigations-Map sich ändert oder sie zu weit von der gewünschten Pfaddistanz entfernt sind.

Wenn sich z.B. die KI auf den Spieler zubewegen soll, sollte die Zielposition nicht in jedem einzelnen Frame auf die Spielerposition gesetzt werden, da dies in jedem Frame einen neuen Pfad abfragt. Stattdessen sollte die Distanz zwischen der aktuellen Zielposition und der Spielerposition verglichen werden, und nur wenn sich der Spieler zu weit entfernt hat, sollte eine neue Zielposition festgelegt werden.

Prüfen Sie nicht in jedem Frame, ob eine Zielposition erreichbar ist. Was wie eine harmlose Prüfung aussieht, ist das Äquivalent einer teuren Pfadabfrage hinter den Kulissen. Wenn der Plan ist, einen neuen Pfad anzufordern, falls die Position erreichbar ist, sollte ein Pfad direkt abgefragt werden. Die Frage "Ist diese Position erreichbar?" wird beantwortet, indem man die letzte Position des zurückgegebenen Pfades betrachtet und prüft, ob diese Position in einer "erreichbaren" Entfernung zur geprüften Position liegt. Dadurch wird vermieden, dass für jedes Frame zwei vollständige Pfadabfragen für denselben NavigationAgent durchgeführt werden.

Teilen Sie die Gesamtzahl der NavigationAgents in Update-Gruppen ein oder verwenden Sie zufällige Timer, damit sie nicht alle im selben Frame neue Pfade anfordern.

Performance-Probleme bei der Synchronisierung von Navigations-Maps

Tipp

Fügen Sie die Polygone von Navigations-Meshes per Vertex statt per Kantenverbindung zusammen, wo immer dies möglich ist.

Wenn Änderungen z.B. an Navigations-Meshes oder Navigationsregionen vorgenommen werden, muss der NavigationServer die Navigation-Map synchronisieren. Je nach Komplexität der Meshes kann dies sehr viel Zeit in Anspruch nehmen, was sich auf die Framerate auswirken kann.

Der NavigationServer vereinigt Navigations-Meshes entweder per Vertex oder per Kantenverbindung. Die Vereinigung per Vertex erfolgt, wenn die beiden Vertices zweier unterschiedlicher Kanten in denselben Map-Rasterzellen landen. Dies ist ein relativ schneller und kostengünstiger Vorgang. Die Vereinigung per Kantenverbindung erfolgt in einem zweiten Durchgang für alle noch nicht vereinigten Kanten. Dabei werden alle freien Kanten auf mögliche Kantenverbindungen anhand von Abstand und Winkel geprüft, was recht aufwändig ist.

Abgesehen von der allgemeinen Regel, so wenig Polygonkanten wie möglich zu haben, sollten also so viele Kanten wie möglich im Vorfeld per Vertex vereinigt werden, damit nur wenige Kanten für die aufwendigere Berechnung der Kantenverbindung übrig bleiben. Die Debug-Navigation PerformanceMonitor kann verwendet werden, um Statistiken darüber zu erhalten, wie viele Polygone und Kanten verfügbar sind und wie viele davon gar nicht vereinigt oder nicht per Vertex vereinigt sind. Wenn das Verhältnis zwischen per Vertex und per Kantenverbindung vereinigten Vertices überhaupt nicht passt (Vertex-Vereinigungen sollte deutlich häufiger vorkommen), werden die Navigations-Meshes nicht richtig erstellt oder sehr ineffizient platziert.