So beheben Sie häufig auftretende Physikprobleme in Ihrem Spiel

Viele Spiele verwenden Physik-Engines, um die Art und Weise zu steuern, wie sich Dinge bewegen und reagieren. Die Verwendung einer Physik-Engine kann Immersionen, Augensüßigkeiten und vor allem das aufkommende Gameplay hinzufügen, kann jedoch bei unsachgemäßer Verwendung zu unrealistischen Ergebnissen oder brechenden Problemen führen. In diesem Beitrag erkläre ich, wie Sie häufige Probleme identifizieren und beheben können, die bei heutigen Spielen auftreten. 

Wir werden diese Probleme aus der Sicht von Unity untersuchen und lösen, wobei wir uns auf die integrierte 3D-Physik-Engine Nvidia PhysX konzentrieren. Die Kernprinzipien können jedoch auf jede andere Plattform und Physik-Engine angewendet werden.

Hinweis: Sie finden eine große Auswahl an 3D-Modellen, um den Einstieg in Envato Market zu erleichtern.

Demo

Diese Demo zeigt die meisten in diesem Artikel erwähnten Fehler sowohl in einem falschen als auch in einem fehlerhaften Zustand und in einem festen Zustand:

Normale Skala

Dies ist eine einfache Szene mit einem Ball, der in einen Stapel von Fässern schlägt. Die alternative Version Falsche Skala (10x) zeigt, wie sich die Szene im 10-fachen Maßstab ändert (siehe Skalenmarkierungen am Boden der Demo). Beachten Sie, wie es sich in Zeitlupe zu befinden scheint, aber dieser Effekt wird einfach durch den Maßstab der Szene verursacht.

Zeichensteuerung

Dies zeigt ein einfaches Side-Scroller-Spiel, das wie beabsichtigt funktioniert. Die "schlechte" Alternative; Rigidbody & Character Controller zusammen zeigt dasselbe Spiel, jedoch mit einer Rigidbody-Komponente, die an den Charakter angehängt ist. Beachten Sie, wie der Rigidbody das Verhalten des Character Controllers durchbricht.

Objekte mit Hingabe

Fässer werden von der Seite der Szene aus geschossen und in die Luft geschleudert. Wenn sie herunterfallen, springen sie vom Boden ab und bewegen sich auf einfache, aber majestätische Weise. Die kaputte Version zeigt dieselbe Szene ohne Schwung und sieht im Vergleich viel langweiliger aus.

Die Transformation eines Rigidbody nicht direkt ändern

In diesem Szenario wird ein schwerer Ball mit einer Rampe nach oben gedrückt Rigidbody.AddForce (). Im zweiten Szenario anstelle von Rigidbody.AddForce () um den Ball die Rampe hinauf zu bewegen, Transform.position wird eingesetzt. Das Ergebnis der Verwendung Transform.position ist, dass die Kugel nach unten rollt, weil der starre Körper die Geschwindigkeitsänderung des starren Körpers nicht richtig berücksichtigt, aber die Positionsänderung bewirkt, dass der Ball die Rampe auf und ab rüttelt.

Häufige Fehler

Falsche Skala

In den meisten Spielen würden die Spieler davon ausgehen, dass der Maßstab der Welt dem Maßstab der Erde entspricht. Sie würden beispielsweise erwarten, dass ein Feind, der von einem Wachturm fällt, mit der gleichen Geschwindigkeit fällt, die Sie auf der Erde wahrnehmen würden. Wenn der Feind zu langsam oder zu schnell abfällt, kann dies das Untertauchen beeinträchtigen - insbesondere, wenn der Feind eine menschliche Größe hat!

Nvidia PhysX in Unity kann eine Einheit pro Meter verwenden. Sie können diese Eigenschaft verwenden, um zu prüfen, ob die Skalierung Ihrer Objekte korrekt ist, indem Sie einfach einen Unity-Grundwürfel hinzufügen. Der primitive Würfel ist genau ein Kubikmeter. Wenn Sie beispielsweise bemerken, dass ein Ölfass in Ihrer Szene zweimal größer ist als der Würfel, bedeutet dies, dass Ihr Ölfass zwei Meter hoch ist.!

Das Festlegen der Skalierung ist so einfach wie das Skalieren jedes Objekts in der Szene. Wählen Sie einfach alle Objekte in Ihrer Szene aus und verwenden Sie die Rahmen Werkzeug, um sie größer oder kleiner zu machen. Wenn Sie bemerken, dass sich Ihre Objekte zu schnell bewegen, vergrößern Sie die Objekte. Wenn Sie das Gegenteil bemerken - die Objekte bewegen sich zu langsam -, sollten Sie die Objekte verkleinern.

Sie können Ihre Objekte präziser skalieren, indem Sie sie in einem Nullobjekt gruppieren und dieses Objekt skalieren. Legen Sie beispielsweise den Maßstab des übergeordneten Objekts auf fest 1.2 Auf jeder Achse wird die Größe jedes Objekts innerhalb des Objekts um 20% erhöht. Sie können die Objekte auch mit dem Skalierwerkzeug in Schritten skalieren, indem Sie gedrückt halten Strg-LMB (Windows) oder Cmd-LMB (OS X).

Einen Rigidbody und einen Character Controller zusammen verwenden

Ich habe gesehen, dass dies einige Male vorgekommen ist, und es macht tatsächlich Sinn, wie oft dies geschieht. Der Entwickler geht davon aus, dass ein Character Controller für die Steuerung seines Avatars erforderlich ist, er möchte jedoch, dass der Avatar von der Schwerkraft und anderen Objekten in der Umgebung beeinflusst wird.

Das Problem ist, dass a Zeichensteuerung ist für klassischere Steuerelemente konzipiert, wie sie normalerweise in einem Plattform- oder Ego-Shooter zu finden sind. EIN Starrer Körper ist einfach ein nicht verformbares Objekt, das durch die Schwerkraft und andere physikalische Kräfte (z. B. andere Objekte, die mit ihm kollidieren) beeinflusst wird. Dies sind zwei sehr separate Komponenten mit unterschiedlichen Verwendungszwecken.

Wählen Sie nur einen Charakter-Controller, wenn Sie die Bewegung des Spielers steuern möchten. Wenn Sie andererseits möchten, dass Ihr Charakter von der Physik-Engine gesteuert wird, verwenden Sie einen Rigidbody. Wenn Sie einem Charakter einen Rigidbody hinzufügen, möchten Sie wahrscheinlich die Rotation einschränken, damit der Spieler nicht umkippen kann.

Die Transformation eines Rigidbody direkt ändern

Im Gegensatz zu einem Charakter-Controller ist es nicht empfehlenswert, die Position oder Rotation eines starren Körpers festzulegen oder ein Objekt eines starren Körpers ständig zu skalieren (für die Steuerung von Spielern usw.). Verwenden Sie stattdessen die AddForce () - und AddTorque () -Methoden, die in der Rigidbody-Klasse gefunden werden. Es ist in Ordnung, die Position und Drehung eines Rigidbody direkt festzulegen, wenn Sie zum Beispiel zum ersten Mal in das Objekt spawnen oder die Szene zurücksetzen. In dieser Situation wird es in Ordnung sein, solange der Rigidbody keine anderen Objekte schneidet.

Dies ist wichtig, da ein starrer Körper, wenn er in eine exakte Position oder einen Rotationszustand bewegt wird, ein Objekt passieren kann. Die Physik-Engine muss dieses Problem dann beheben, und die Physik-Engine läuft meistens nicht zur gleichen Zeit wie Unity Aktualisieren() Nachricht tut. Das Endergebnis ist unruhiges Verhalten, wenn eine Schnittmenge vorhanden ist, und es ist möglich, dass der starre Körper Objekte vollständig durchläuft.

Ein anderer negativer Nebeneffekt, der auftreten kann, wenn beispielsweise ein starrer Körper entlang einer Achse bewegt wird, ist, dass der starre Körper intern simuliert wird und dann seine Position anwendet. Das Aktualisieren der Position bewegt dann den starren Körper ohne Berücksichtigung der Geschwindigkeitsänderung und dergleichen. Wenn der starre Körper einen Abhang hinunterrollt, bewegt er den starren Körper nach hinten, während Ihre Position, die den Code ändert, den starren Körper den Abhang hinauf bewegt.

Objekte rollen für immer

Nehmen wir an, Sie entwickeln ein Golfspiel. Es gibt ein Problem damit, wie der Golfball nicht aufhört zu rollen, und es gelingt irgendwie, immer weiter zu rollen, solange sich kein Loch oder Graben in seinem Weg befindet. Der Grund dafür ist, dass der Ball im wirklichen Leben unter anderem durch das Gras, auf dem er läuft, verlangsamt wird, da er die winzigen Grashalme nach unten drücken muss. Das Gras ist im Wesentlichen wie eine konstante Rampe. Das nennt man Rollwiderstand. Unity kann dieses Verhalten nicht genau simulieren. Stattdessen müssen künstliche Haltekräfte verwendet werden.

In Unity ist die beste Kraft, die verwendet werden muss, um zu verhindern, dass ein Objekt für immer rollt, "Winkelwiderstand". Durch die Änderung des Winkelwiderstands am Golfball kann dieses Problem behoben werden. Der genaue Wert hängt wirklich von dem Verhalten ab, nach dem Sie suchen. In einigen Fällen ist ein Winkelwiderstand von 1,0 jedoch möglicherweise nicht ausreichend.

Objekte ohne Hingabe

Nahezu jedes Objekt der Welt springt nach einem Aufprall ab. Das interne standardmäßige Physikmaterial von Unity hat keinerlei Sprungkraft. Das bedeutet, dass jedes Objekt nicht abprallt, es sei denn, Sie überschreiben das Standardmaterial für die Physik oder wenden ein Physikmaterial auf die Objekte in Ihrer Szene mit einem Sprungwert von mehr als 0 an.

Eine der besten Möglichkeiten, dieses Problem zu beheben, besteht darin, ein eigenes Standard-Physik-Material zu erstellen und es im zuzuordnen Physik-Manager gefunden durch Anklicken Bearbeiten> Projekteinstellungen> Physik.

Rigidbodies versenken teilweise in die Geometrie

Die meisten Physik-Engines verfügen über eine Art Parameter, der vorschreibt, wie viel zwei Objekte sich durchdringen oder überschneiden können, bis sie voneinander weggedrückt werden. Dieser Parameter wird Min Penetration For Penalty in Unity genannt. Standardmäßig beträgt dieser Wert 0,01 (Meter). Dies bedeutet, dass sich Objekte standardmäßig bis zu 1 cm schneiden können, bevor sie auseinander gedrückt werden.

Sie sollten einstellen Min. Penetration für Strafe auf einen Wert, bei dem es kaum merklich ist, dass sich Objekte schneiden. Den Wert auf etwas Winziges einstellen, wie z 0,0001, kann zu unruhigen starren Körpern führen.

So vermeiden Sie Fehler

Code schreiben für starre Körper (für Programmierer)

Wenn Sie kein Programmierer sind, müssen Sie sich nicht um das folgende Szenario kümmern. Wenn Sie Code schreiben, der starre Bodies bewegt, rotiert oder skaliert, ist es wichtig, diesen in der FixedUpdate-Schleife zu behalten. Schreiben Sie diesen Code in die Aktualisieren Schleife führt möglicherweise zu instabilen Ergebnissen, da die Aktualisieren Funktion kann bei 1000 Hz aufgerufen werden, während die Physik-Engine und die FixedUpdate Funktion werden standardmäßig mit 50 Hz aufgerufen. 

Sie können die Frequenz für physikalische Schritte ändern, indem Sie den Parameter ändern Fixed Timestep, gefunden in Bearbeiten> Projekteinstellungen> Zeit. Der Wert legt fest, wie viel Zeit zwischen den einzelnen Physik-Updates oder -schritten in Sekunden gewartet wird. Sie können die Frequenz in Hertz ermitteln, indem Sie 1 durch den Wert dividieren (zum Beispiel bedeutet eine Wartezeit von 0,01 Sekunden 1 / 0,01 = 100 Hz). Je häufiger die Schritte sind, desto genauer und stabiler wird die Simulation sein. Wenn Sie die Frequenz jedoch höher einstellen, als von der CPU verarbeitet werden kann, führt dies zu einer sehr instabilen Simulation. Versuchen Sie, die Frequenz der festen Aktualisierung zwischen 30 Hz und 100 Hz zu halten.

Bei der Arbeit an einer zerstörbaren Ziegelmauer stieß ich auf ein Problem, das durch das Instanziieren von Ziegeln hervorgerufen wurde, nachdem ein Teil der Mauer zerstört worden war. Ich habe dieses Problem behoben, indem der problematische Code in eine Coroutine eingefügt und die folgende Zeile vor dem Objekt Zerstören eingefügt wurde:

// Warten Sie auf eine Frame-Rendite. // C # Ausbeute; // UnityScript

Beim Warten auf einen Frame würde dies garantieren, dass die Logik in der Update-Zeit und nicht in der FixedUpdate-Zeit synchronisiert wurde. Dies scheint zu bedeuten, dass die Destroy-Funktion synchron mit der Update-Schleife ausgeführt wird.

Bonus-Unity-Tipp: Verwenden Sie nicht die Standardmaterialien für Physik!

Das Physics-Material-Paket, das Bestandteil der Unity-Standard-Assets ist, ist eigentlich fast völlig nutzlos. Das Paket enthält fünf physikalische Materialien, die alle in gewisser Weise unrealistisch sind. 

Jedes Material hat identische statische und dynamische Reibung. In der realen Welt haben Objekte, die still stehen, etwas mehr Reibung als wenn sie sich bewegen. Der Reibungskoeffizient des Gummimaterials beträgt 1,0, Das ist keinem Gummi ähnlich, der in der realen Welt gefunden wird. Und wenn das nicht albern genug klingt, hat jedes Material 0 "Hüpfburg" (mit Ausnahme des "Bouncy" -Materials). Dies alles bedeutet, dass die Materialien nicht einmal eine genaue Darstellung ihres realen Gegenstücks darstellen. 

Es ist am besten, wenn Sie Ihr eigenes Physikmaterial erstellen. Es gibt viele Websites, die physikalische Eigenschaften von Materialien gemeinsam haben - die wichtigsten sind dynamische Reibung, statische Reibung und Restitution.

Fazit

Sehr wenige Probleme in Bezug auf Physik sind tatsächlich so schwer zu beheben. Wenn es einen physikbedingten Fehler gibt, der schwer aufzuspüren scheint, versuchen Sie, die Zeit zu verlangsamen, um zu sehen, was los ist. Wenn Sie bemerken, dass das Problem in einer bestimmten Codezeile beginnt, können Sie Debug.Break verwenden, um den Editor anzuhalten und zu überprüfen, was los ist. Fühlen Sie sich frei, hier zu kommentieren, wenn Sie Fragen haben oder Hilfe benötigen.