Überwindung von Float-Einschränkungen für Welten in Planetengröße in Unity

8

Soweit ich weiß, ist es aufgrund von Gleitkommapräzisionsproblemen kaum möglich, mehr als 1 Million Einheiten vom weltweiten Ursprung in Unity zu entfernen.

Um eine Welt mit einem Radius von mehr als 1 Million Einheiten zu erstellen, müssten entweder doublevars als Koordinaten verwendet oder eine Raumteilungstechnik verwendet werden, um eine massive Szene in hierarchische Blöcke zu unterteilen, wobei der kleinste von ihnen etwa 10 000 Einheiten beträgt, dh jede Weltraumposition würde ausgedrückt Durch die Blockhierarchie befindet sich das Objekt in und eine Reihe von floatVariablen, die seine lokale Position (und möglicherweise Rotation und Skalierung) innerhalb des letzten Blocks darstellen.

In jedem Fall müsste dazu ein komplett neues Koordinatensystem implementiert werden. Daher möchte ich wissen, ob dies in Unity möglich ist oder nicht, und wenn ja, wie kann ich dafür sorgen, dass es mit vorhandenen Unity-Systemen wie Physik usw. funktioniert.

PS Ich kann die Welt nicht einfach in ihren Ursprung versetzen, während sich der Spieler bewegt, da ich möchte, dass die Dinge gleichzeitig auf dem Planeten vor sich gehen.

Vielen Dank!

Macht Maisak
quelle

Antworten:

5

Sie denken sehr statisch.

Nur weil ein Objekt eine halbe Welt entfernt ist, sind keine Probleme erforderlich. Wenn Entitätskoordinaten relativ zum Block und nicht relativ zur Welt gespeichert werden, ist dies trivial zu erreichen. Willkommen bei der Art und Weise, wie Sie dies tun müssten, wenn Sie eine Voxelwelt in nativem Code schreiben würden.

Nehmen wir also ein Konzept namens locales an . Es ist eine Reihe von Stücken, die sich in unmittelbarer Nähe zueinander befinden. Was zählt, ist, dass der Float-Raum innerhalb eines bestimmten Gebietsschemas niemals die Sicherheitsgrenze überschreitet. Sie müssen bestimmen, was Ihre diskreten Verarbeitungsgebiete sind. Beginnen Sie, indem Sie alle Blöcke nehmen, die in einen Radius von der Position der Entität n fallen (könnte der Spieler oder etwas anderes sein). In meiner aktuellen Engine stelle ich sicher, dass diese Gebietsschemas zu einem Gebietsschema / Satz eindeutiger Blöcke zusammengeführt werden, wenn sich auch nur ein Teil von zwei verschiedenen Gebietsschemas überlappt. Dies stellt sicher, dass Sie niemals alle Entitäten in einem einzelnen Block mehr als einmal in einem bestimmten Frame verarbeiten.

Nachdem Sie Ihre Gebietsschemas / Chunk-Sets haben, können Sie Spiellogik für sie und ihren Inhalt ausführen. Und es spielt keine Rolle, wie weit sie vom Spieler oder vom Ursprung entfernt sind. Was zählt, ist, dass Sie einen Block erhalten, der ungefähr zentral für jeden Satz ist, diesen als Ursprung behandeln, dh float[0.0,0.0,0.0], und sich von dort nach außen arbeiten. Angesichts der typischen Sichtweite in einem Spiel garantiere ich Ihnen, dass Sie nie mehr als ein paar Kilometer sehen müssen, was floatohne ernsthafte Probleme sehr gut möglich ist.

Abgesehen von Unity besteht eine Option darin, eine Engine von Grund auf neu zu schreiben und so etwas wie libfixmath zu verwenden, wobei Sie immer noch Dezimalstellen verwenden können. Da diese jedoch nicht schweben , treten diese Genauigkeitsprobleme nie auf. Aber ich garantiere Ihnen, dass Sie aus anderen Gründen Brocken und Gebietsschemas benötigen, sodass sich die Mühe wahrscheinlich nicht lohnt.

Ingenieur
quelle
Sie sagten, dass ich nie mehr als ein paar Kilometer entfernt sehen muss, aber was ist mit einer Welt in Planetengröße, die ich vom Weltraum aus vollständig beobachten kann (siehe Outerra )?
Maks Maisak
@MaksimMaisak Die Spielelogik erfordert numerische Genauigkeit. Rendern nicht. Sie müssen die detaillierte, präzise Welt nie aus dem Weltraum sehen. Es gibt eine bestimmte Höhe, in der Sie nahtlos von dem oben beschriebenen genauen System am Boden zu der weniger genauen Raumperspektive wechseln können (wenn Sie Ihre Karten richtig spielen). Bedenken Sie jedoch, dass es einen Unterschied zwischen Rendering und Spielelogik gibt.
Ingenieur
Und wie teilt man den Raum in Stücke? Beginnen Sie mit Chunks und gruppieren Sie sie in Gebietsschemas oder beginnen Sie mit Gebietsschemas und teilen Sie sie in Chunks auf?
Maks Maisak
Sie beginnen mit Brocken. "Locales" bedeutet hier nur "Nachbarschaften von Chunks", daher ist das Chunk-Konzept die Voraussetzung.
Ingenieur
Wie kann sich ein Stück dann überlappen?
Maks Maisak
6

Das ist eine Frage, die häufig auftaucht. Ich werde mir erlauben, Sie zu einer weiteren ziemlich detaillierten Antwort weiterzuleiten, die ich bereits auf dasselbe Problem gegeben habe, anstatt es hier nur zu wiederholen: Ist in Unity ein benutzerdefiniertes Koordinatensystem möglich?

Von dort aus würde ich am meisten vorschlagen, dass Sie das erstaunliche Papier lesen unter: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.471.7201&rep=rep1&type=pdf . Es werden einige Möglichkeiten verglichen, um das von Ihnen beschriebene Problem anzugehen (einschließlich lokaler Koordinaten, wie von Arcane Engineer in seiner Antwort beschrieben), und es werden Details zur heutzutage bekannten Float-Origin-Lösung erläutert. Genau das würde ich in den meisten Fällen tun (genau das verwende ich in meiner Anwendung).

Sicher, Sie haben erwähnt, dass die Float-Origin-Lösung nicht Ihren Anforderungen entspricht. Dies ist jedoch möglicherweise nicht der Fall, selbst wenn Sie möchten, dass in sehr weit entfernten Teilen der Welt weiterhin Dinge geschehen. Sie können so ziemlich jede KI haben, wo immer Sie wollen - Sie sollten einfach keine Kollisionsprüfungen oder präzise Positionierungen zu weit vom Spieler entfernt durchführen (dh jenseits der Schwimmer-Ungenauigkeitsschwelle). Aber ehrlich gesagt, in realen Anwendungen könnten Sie aufgrund von Verarbeitungsbeschränkungen wahrscheinlich nie so viele Kollisionen und Positionen in einem Spiel haben. Abhängig von den Eigenschaften Ihres Spiels gibt es möglicherweise sogar Lösungen für diese Einschränkung, die Sie bei der Float-Origin-Lösung sehen. Auch hier schlage ich vor, dass Sie diese Lösung nicht verwerfen, bevor Sie sie gründlicher gelesen haben.

Wenn Sie sich jedoch dazu entschließen, lokale Koordinatensysteme auszuprobieren (was je nachdem, wohin Sie gehen, zu einer recht komplexen Lösung werden kann), ist der zweite Punkt in meiner verknüpften Antwort für Sie. Das wichtigste Stück dort ist das Papier, das von dem Typ geschrieben wurde, der diese Lösung zum ersten Mal im Pionierspiel Dungeon Siege implementiert hat: http://scottbilas.com/files/2003/gdc_san_jose/continuous_world_paper.pdf

Es gibt auch ein Video von vor ein paar Jahren, in dem Leute von Unity diese Lösung kommentieren und sogar eine moderne Implementierung des Konzepts in Unity erklären:

https://www.youtube.com/watch?v=VKWvAuTGVrQ

Ich hoffe es hilft.

MAnd
quelle
3

Ich bin mir nicht sicher, ob Sie sich bereits für eine Lösung entschieden haben, aber ich möchte zwei weitere Ressourcen erwähnen, die für Sie und andere Leser in Zukunft nützlich sein könnten.

  • Dieser aktuelle CppCon-Vortrag: "Demystifying Floating Point" , der unabhängig von der Programmiersprache sehr relevant ist. Ein sehr interessanter Punkt zur Präzision ist, dass der Sweet-Spot der Float-Genauigkeit zwischen dem Bereich [-1, + 1] liegt. Normalisierte Schwimmer sind also der beste Weg, wenn Sie sie verwenden können.

  • Ein weiterer Ort, an dem Sie nach Ideen suchen möchten, ist das klassische Dungeon Siege- Spiel. Das Spiel verwendete ein kontinuierliches Weltsystem, das auf Knoten / Kacheln basierte und jede Position war relativ zum aktuellen Knoten. In diesem Whitepaper finden Sie eine sehr detaillierte Beschreibung des vom Spiel verwendeten Systems . Ich habe auch ein paar Absätze darüber in meinem Blog geschrieben . Dieses Setup war zu dieser Zeit neu, aber es ist heute wahrscheinlich nicht so nützlich. In dem oben verlinkten Papier werden einige der Probleme erwähnt, die sie hatten. Trotzdem ist es aus historischer Sicht interessant und kann Ihnen dennoch als Quelle für Ideen und Inspiration dienen.

glampert
quelle