Langsame Kollisionserkennung bei niedrigen Bildraten

8

Ich habe ein seltsames Problem mit meiner Kollisionserkennung. Ich verwende die Update-Methode, um den Player zu verschieben (ich möchte FixedUpdate nicht verwenden, da dies eine unerwünschte seltsame Bewegung verursacht). Der feste Zeitschritt ist auf den Standardwert 0,02 eingestellt (ich habe versucht, mit der Zeiteinstellung zu spielen, aber das hat auch nicht funktioniert). Ich setze die Kollisionserkennung der starren Körper beider Objekte auf "kontinuierliche Dynamik". Außerdem habe ich die Zielbildrate auf 300 gesetzt, und das hat nichts geändert ...

Wenn die Framerate niedrig ist oder das Gerät selbst langsam ist, funktioniert die Kollisionserkennung nicht immer. Der Spieler kann leicht durch das Objekt fallen, mit dem er kollidieren soll, obwohl dies manchmal nicht der Fall ist.

Bitte sag mir, was ich tun kann, um das Problem zu beheben, weil ich ein Spiel veröffentlicht habe und viele Benutzer diesen (schwerwiegenden) Fehler melden. Danke für Ihre Unterstützung.

Das soll passieren:

Das passiert tatsächlich:

(wie Sie sehen können, kommt der Würfel aus der Wand und auf die andere Seite)

Ich bewege den Player, wenn der Benutzer die Maustaste loslässt:

Skript 1:

%Vor%

An Spieler (Würfel) angehängtes Skript 2:

%Vor%

Das Ziel des Würfels ist ein Kind des größeren Würfels (der Wand).

Wenn Sie eine Erläuterung benötigen, hinterlassen Sie bitte einen Kommentar. Ich könnte den Link zu meinem Spiel geben, wenn Sie weitere Informationen benötigen.

Zitat von hier (gefunden dank @Logman): "Das Problem besteht auch, wenn Sie eine kontinuierliche dynamische Kollisionserkennung verwenden, weil sich schnell bewegende Objekte so schnell bewegen können, dass sie von einem Frame zum nächsten unmittelbaren Frame zu weit voneinander entfernt sind. Es ist so, als ob sie teleportiert und es würde niemals eine Kollisionserkennung ausgelöst werden, weil keine Kollision existiert, aus jeder Frame-Perspektive und somit aus allen Berechnungen, die verarbeitet wurden. "

In meinem Fall geht der Würfel nicht schnell, aber Sie bekommen das Konzept.

    
Dinovr 12.06.2016, 12:22
quelle

2 Antworten

7

Es gibt mehrere Probleme mit Ihrem Code.

  1. Du verlangst von einer Coroutine, dass sie für 1/50 einer Sekunde nachgibt. Die Mindestzeit, für die ein Ertrag eintreten muss, ist ein Rahmen. Wenn Time.deltaTime > 0.02f ist dies bereits eines der Probleme.
  2. Sie verwenden Coroutines und yield return null , um physikalische Berechnungen zu berechnen. Im Wesentlichen berechnen Sie Physik in Update() , die nur einmal pro Frame genannt wird ( null entspricht new WaitForEndOfFrame() : Wie in (1) erwähnt, kann eine laufende Coroutine nicht nachgeben zwischen Rahmen). Bei niedriger Bildrate kann der Bewegungsumfang, den ein Objekt zwischen zwei Bildern einnimmt, den Kollisionsbereich des Zieltriggers überschreiten. Unter der Annahme linearer, nicht beschleunigender Bewegung: ∆S = v∆t mit v = Geschwindigkeit, ΔS ist die Bewegung, die im aktuellen Rahmen abgedeckt werden soll, Δt ist Time.deltaTime . Wie Sie sehen können, skaliert ΔS proportional zu Δt.

  3. Sie haben GetComponent<T>() Aufrufe in Loops. Vermeiden Sie immer Folgendes: Speichern Sie stattdessen eine Referenz als eine Mitgliedsvariable (initialisieren Sie sie in Start() ).

Mein Vorschlag für den schnellsten Arbeits-Hack wäre, sich nicht zu sehr Sorgen zu machen, "sauber zu sein", und stattdessen Unterroutinen zu erstellen, die Sie von FixedUpdate() aufrufen, und (create und) verwenden Sie das Mitglied bool s, um das zu testen Subroutine zu "ausführen" und die zu "überspringen". Sie können auch die Mitglieder bool s oder enum s als Auslöser verwenden, um zwischen verschiedenen "Zuständen" zu wechseln.

Eine bessere Lösung wäre es, Unity die Kinematik handhaben zu lassen und stattdessen mit rigidbody mutators (und nicht transform.position s) zu arbeiten, aber das ist für eine Arcadesituation völlig unnötig. In diesem Fall bleib bei dem obigen Hack.

Wenn Sie wirklich Kinematiken von Hand steuern möchten, verwenden Sie eine Engine wie SFML. Ein Particle System Tutorial wäre ein guter Anfang.

    
sloth 22.06.2016 06:27
quelle
4

Es ist Ihr float Prozentsatz unter anderem.

"Wenn isKinematic aktiviert ist, wirken Kräfte, Kollisionen oder Gelenke nicht mehr auf den Starrkörper."

Das stammt von der isKinematic-Seite der Unity-Dokumentation. Sie setzen es auf "true", wenn der Fortschritt 100 erreicht. Bei niedrigeren Framerates gibt es also einen plötzlichen Sprung, da die Schritte von Time.deltaTime viel höher sind, der Fortschritt plötzlich & gt; = 100 ist, isKinematic auf "True" gesetzt ist und Spieler ist nicht mehr von Kollisionen betroffen.

Ich denke, dass Sie hier viel Code überdenken müssen und einige starke Optimierungen vornehmen müssen. Aber die anderen Plakate haben das schon rausgelegt, also muss ich nicht.

BEARBEITEN: Die erste Frage falsch verstanden, dachte, dass es bedeutete, dass Sie versuchten, Kollisionen zu erkennen, aber Ihr Code erkannte sie nicht immer. Ich wusste nicht, dass es eigentlich bedeutet, dass die Kollisionen überhaupt auftreten.

    
DisturbedNeo 22.06.2016 09:24
quelle

Tags und Links