2017-02-16 5 views
3

Ich weiß, wenn ich zu viele Dinge in update() tun würde die Konsequenz würde fallen Bildrate unter der Zielbildfrequenz. Aber was würde passieren, wenn ich dasselbe in fixedUpdate() mache?Was ist die Konsequenz von schwerer Arbeit in fixedUpdate()?

Würde es Unity's Physik Engine versauen, oder würde es das Programm zum Absturz bringen?

+1

Einige gute Antworten [hier] (http://answers.unity3d.com/questions/202614/and-yet-more-questions-about-fixedupdate.html) und [hier] (http: // answers.unity3d.com/questions/10993/whats-the-difference-between-update-and-fixedupdat.html) – DeclanPossnett

+0

@DeclanPossnett Also mit anderen Worten, wenn ich eine 20ms default fixedTimeFrame und meine fixedUpdate() dauern 100ms zu laufen , wird sich die Spielwelt 5 mal langsamer bewegen, als es sollte? – AVAVT

+1

Grundsätzlich erklärt die _best_ Antwort auf [diese Einheitsfrage] (http://answers.unity3d.com/questions/10993/whats-the-difference-between-update-and-fixedupdat.html), dass Sie normalerweise die die gewünschte Anzahl an Physikupdates pro Frame natürlich innerhalb von Unity - aber wenn du die Physik-Engine so stark belastest, würde sie die Bildrate nicht erreichen und somit nicht simulieren! – DeclanPossnett

Antwort

3

Die Antworten und Kommentare waren sehr hilfreich, aber sie haben keine klare, informative Antwort auf meine Frage. Jeder weiß, dass schlimme Dinge passieren werden, wenn Sie zu viel Arbeitslast in die FixedUpdate() Schleife legen, meine Frage war was schlechte Sache wird dann passieren.

Da ich endlich meine Hand am Computer hatte, beschloss ich, selbst einen Test zu machen. Nur als Referenz das ist was ich getestet habe:

public class TestFixedUpdate : MonoBehaviour { 
    public int loopNo = 500000; 

    private int noOfCall = 0; 
    private int collisionTimes = 0; 

    private void FixedUpdate() 
    { 

     if (noOfCall > 100) return; 
     float time = Time.timeSinceLevelLoad; 

     for (int i = 0; i < loopNo; i++) { 
      Quaternion.Slerp(Quaternion.identity, Quaternion.FromToRotation(Vector3.up, Vector3.forward), Mathf.Abs(Mathf.Sin(Time.timeSinceLevelLoad))); 
     } 

     Debug.Log(Time.timeSinceLevelLoad.ToString("0.00")); 

     if (noOfCall > 99) Debug.Log("Simulation finished. Times collided:" + collisionTimes); 

     noOfCall++; 
    } 

    private void OnCollisionEnter(Collision collision) 
    { 
     if (noOfCall > 100) return; 
     collisionTimes++; 
     Debug.Log("Times collided:" + collisionTimes); 
    } 
} 

Ich lege es auf eine Kugel, die kontinuierlich auf einem Flugzeug abprallen wird. Der Test wurde durchgeführt, indem die Funktion von FixedUpdate() und Update() geändert wurde und die Unterschiede verglichen wurden.

Der Hauptunterschied, den ich herausgefunden habe, war, dass im Fall von FixedUpdate() Unity's simulierte Time (die Zeit der Spielwelt) nicht synchron mit der tatsächlichen Zeit ist. Mit anderen Worten, jede Funktion, die vom System Time von Unity abhängt, wirkt so, als ob die ganze Welt langsamer geworden wäre.

auch:

  1. Unity berichtet die gleiche Bildrate für beide Fälle, auch wenn für die FixedUpdate() Fall ist es offensichtlich, dass die tatsächliche Bildrate - der Rahmen pro Sekunde realen Welt - ist deutlich geringer.

  2. Neben der Verlangsamung scheinen Kollisionserkennung und Physiksimulationslogik wie gewohnt zu funktionieren. Körper, die kollidieren sollten, kollidieren noch immer; Beschleunigung, Kraftanwendung usw. funktionieren noch. Starrkörper, die nicht innerhalb von 20ms (Unity's ms) durch einen Collider springen, kollidieren und prallen wie gewohnt zurück.

  3. Die Maximum Allowed Timestep Option in den Projekteinstellungen definiert die maximale Anzahl von (Unity's simulierte Zeit), bevor ein Frame gezeichnet werden muss (ich wusste nie, wofür es vorher war). Klarstellung: Wenn ich es auf 0,5 Sekunden setze, wird egal, wie viel Code ich in beide Funktionen einfüge, der Logik-Aktualisierungsschritt (Update()) sofort aufgerufen, nachdem eine FixedUpdate() Runde die 0,5-te Sekunde simuliert hat, und dann wird die Szene gerendert werden.

0

Der Motor blockiert während der Verarbeitung einer schweren Last (z. B. wenn Sie eine Endlosschleife ausführen) innerhalb einer beliebigen Funktion. Dinge, die auf Time.DeltaTime beruhen, beginnen sich zu verhalten, wenn die Bildrate zu niedrig fällt. Es spielt keine Rolle, ob das Update oder FixedUpdate ist.

Was Sie tun können, wenn Sie einen Prozess benötigen, um eine schwere Last zu betreiben, ist es, eine Coroutines z. IEnumerator-Funktion und Ausbeute, mit der Sie die Verarbeitung auf mehrere Frames aufteilen oder eine Funktion über einen Callback aufrufen können. z.B. Wenn Sie einen AI-Check-Pfad 5 Mal pro Sekunde haben, können Sie entweder in Update mit einem Zähler für jeden Frame umgehen oder Sie können einen Rückruf planen.

Im Grunde wird es eine Grenze geben, wie viel Code pro Frame ausgeführt werden kann, ohne die Leistung zu beeinträchtigen. Cleveres Neuschreiben sollte das überflüssig machen. Sehen Sie, ob Sie Ergebnisse von Berechnungen zwischenspeichern oder so viel Daten wie möglich außerhalb des Spiels berechnen können.

Verwandte Themen