Menu
CoddyTech

FixedUpdate pour la physique

Fait partie de la section Physique et gameplay du Journey Unity de Coddy. Leçon 4 sur 71.

Unity déplace les corps selon des pas de physique fixes de 0.02 seconde (Time.fixedDeltaTime), 50 fois par seconde, quel que soit le taux d’images. FixedUpdate() s’exécute juste avant chaque pas. Update() s’exécute une fois par image affichée, et cela peut arriver 30, 60 ou 144 fois par seconde : à 144, la plupart des images n’ont aucun pas de physique, et sur un ordinateur lent, une image peut en contenir deux.

Deux règles en découlent. Une force ajoutée dans Update() l’est une fois par image, donc un ordinateur plus rapide pousse plus fort : les forces qui agissent au fil du temps doivent être appliquées dans FixedUpdate(). Et GetKeyDown n’est vrai que pendant une seule image ; si cette image ne comporte aucun pas de physique, FixedUpdate() ne le détecte jamais et la pression est perdue. Il faut donc lire les pressions dans Update(), les mémoriser dans un bool, puis agir en conséquence dans FixedUpdate(). Ce bateau est poussé par un vent constant et fait une embardée sur le côté d’un clic :

private bool dashQueued;

void Update()
{
    if (Input.GetMouseButtonDown(0))
    {
        dashQueued = true;   // mémoriser le clic
    }
}

void FixedUpdate()
{
    rb.AddForce(Vector3.forward * wind);   // une poussée constante, à chaque étape
    if (dashQueued)
    {
        rb.AddForce(Vector3.right * 4f, ForceMode.Impulse);
        dashQueued = false;   // un clic, un dash
    }
}

Il est important de remettre le bool à zéro après l’avoir utilisé : s’il restait à true, le bateau ferait une embardée à chaque pas. Une seule impulsion pourrait aussi être ajoutée directement depuis Update(), comme pour le saut de la grenouille ; le bool permet de regrouper toutes les poussées au même endroit, à côté des forces avec lesquelles il agit. Les touches maintenues (GetKey, GetAxis) décrivent un état plutôt qu’un instant ; FixedUpdate() peut donc les lire directement. Dans FixedUpdate(), Time.deltaTime renvoie la durée du pas, soit 0.02.

challenge icon

Défi

Facile

Place les deux tâches de la luge dans les bonnes méthodes.

  1. Déplace les deux blocs if des flèches de Update() vers FixedUpdate().
  2. Ajoute private bool hopPressed;. Dans Update(), définis-le sur true lorsque Input.GetKeyDown(KeyCode.Space) est détecté.
  3. Dans FixedUpdate(), lorsque hopPressed est défini, ajoute l’impulsion, puis définis-le sur false.

Appuie sur « Jouer » : les flèches propulsent la luge uniformément, et chaque pression sur Espace la fait bondir. Puis clique sur « Vérifier ».

Essayez vous-même

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);
        }
    }
}

Toutes les leçons de Physique et gameplay

Entraînez-vous par vous-même : Playground Unity