Menu
CoddyTech

FixedUpdate für Physik

Teil des Abschnitts Physik und Gameplay der Unity-Journey von Coddy. Lektion 4 von 71.

Unity bewegt Körper in festen Physikschritten von 0.02 Sekunden (Time.fixedDeltaTime), 50-mal pro Sekunde, unabhängig von der Bildrate. FixedUpdate() wird direkt vor jedem Schritt ausgeführt. Update() wird einmal pro gerendertem Frame ausgeführt, und das kann 30-, 60- oder 144-mal pro Sekunde sein: Bei 144 haben die meisten Frames überhaupt keinen Physikschritt, und auf einem langsamen Computer kann ein Frame zwei Schritte enthalten.

Daraus folgen zwei Regeln. Eine in Update() hinzugefügte Kraft wird einmal pro Frame hinzugefügt, sodass ein schnellerer Computer stärker schiebt: Kräfte, die über längere Zeit wirken, gehören in FixedUpdate(). Und GetKeyDown ist nur für einen Frame lang wahr; wenn dieser Frame keinen Physikschritt hat, bekommt FixedUpdate() es nie mit und der Tastendruck geht verloren. Lies Tastendrücke also in Update() aus, speichere sie in einem bool und reagiere in FixedUpdate() darauf. Dieses Boot wird von einem stetigen Wind geschoben und saust bei einem Mausklick seitwärts:

private bool dashQueued;

void Update()
{
    if (Input.GetMouseButtonDown(0))
    {
        dashQueued = true;   // den Klick merken
    }
}

void FixedUpdate()
{
    rb.AddForce(Vector3.forward * wind);   // ein gleichmäßiger Schub bei jedem Schritt
    if (dashQueued)
    {
        rb.AddForce(Vector3.right * 4f, ForceMode.Impulse);
        dashQueued = false;   // ein Klick, ein Sprint
    }
}

Es ist wichtig, den bool nach seiner Verwendung zurückzusetzen: Ließe man ihn auf true, würde das Boot bei jedem Schritt losschießen. Ein einzelner Impuls könnte auch direkt in Update() hinzugefügt werden, wie beim Sprung des Froschs; der bool hält alle Schübe an einem Ort, neben den Kräften, mit denen er zusammenwirkt. Gedrückte Tasten (GetKey, GetAxis) beschreiben einen Zustand statt eines Moments, daher kann FixedUpdate() sie direkt auslesen. Innerhalb von FixedUpdate() gibt Time.deltaTime die Dauer des Schritts von 0.02 zurück.

challenge icon

Aufgabe

Einfach

Ordne die beiden Aufgaben des Schlittens den richtigen Methoden zu.

  1. Verschiebe die beiden if-Blöcke für die Pfeiltasten aus Update() nach FixedUpdate().
  2. Füge private bool hopPressed; hinzu. Setze es in Update() bei Input.GetKeyDown(KeyCode.Space) auf true.
  3. Füge in FixedUpdate(), wenn hopPressed gesetzt ist, den Impuls hinzu und setze es anschließend auf false.

Drücke auf „Spielen“: Die Pfeiltasten schieben den Schlitten gleichmäßig an, und bei jedem Druck auf die Leertaste springt er. Drücke dann auf „Prüfen“.

Probier es selbst

using UnityEngine;

public class Sled : MonoBehaviour
{
    public float push = 6f;
    public float hop = 5f;
    private Rigidbody rb;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }

    void Update()
    {
        if (Input.GetKey(KeyCode.RightArrow))
        {
            rb.AddForce(Vector3.right * push);
        }
        if (Input.GetKey(KeyCode.LeftArrow))
        {
            rb.AddForce(Vector3.left * push);
        }
    }

    void FixedUpdate()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            rb.AddForce(Vector3.up * hop, ForceMode.Impulse);
        }
    }
}

Alle Lektionen in Physik und Gameplay

Übe selbstständig: Unity-Playground