Menu
CoddyTech

FixedUpdate para física

Parte de la sección Física y jugabilidad del Journey de Unity de Coddy. Lección 4 de 71.

Unity mueve los cuerpos en pasos de física fijos de 0.02 segundos (Time.fixedDeltaTime), 50 por segundo, independientemente de la frecuencia de fotogramas. FixedUpdate() se ejecuta justo antes de cada paso. Update() se ejecuta una vez por cada fotograma dibujado, y eso puede ser 30, 60 o 144 veces por segundo: a 144, la mayoría de los fotogramas no tienen ningún paso de física, y en un ordenador lento un fotograma puede contener dos.

De aquí se desprenden dos reglas. Una fuerza añadida en Update() se añade una vez por fotograma, así que un ordenador más rápido empuja con más fuerza: las fuerzas que actúan a lo largo del tiempo van en FixedUpdate(). Además, GetKeyDown es verdadero durante un solo fotograma; si ese fotograma no tiene ningún paso de física, FixedUpdate() nunca lo detecta y se pierde la pulsación. Por eso, lee las pulsaciones en Update(), guárdalas en un bool y actúa en consecuencia en FixedUpdate(). Esta barca recibe el empuje constante del viento y se desplaza lateralmente con un clic:

private bool dashQueued;

void Update()
{
    if (Input.GetMouseButtonDown(0))
    {
        dashQueued = true;   // recuerda el clic
    }
}

void FixedUpdate()
{
    rb.AddForce(Vector3.forward * wind);   // un empuje constante en cada paso
    if (dashQueued)
    {
        rb.AddForce(Vector3.right * 4f, ForceMode.Impulse);
        dashQueued = false;   // un clic, un impulso
    }
}

Es importante borrar el valor booleano después de usarlo: si se dejara en true, se desplazaría en cada paso. También se podría añadir un único impulso directamente desde Update(), como se hacía con el salto de la rana; el valor booleano mantiene todos los empujes en un solo lugar, junto a las fuerzas con las que interactúa. Las teclas mantenidas (GetKey, GetAxis) describen un estado, no un instante, así que FixedUpdate() puede leerlas directamente. Dentro de FixedUpdate(), Time.deltaTime devuelve el valor de 0.02 del paso.

challenge icon

Desafío

Fácil

Coloca las dos tareas del trineo en los métodos correctos.

  1. Mueve los dos bloques if de las flechas de Update() a FixedUpdate().
  2. Añade private bool hopPressed;. En Update(), asígnale true cuando se pulse Input.GetKeyDown(KeyCode.Space).
  3. En FixedUpdate(), cuando hopPressed esté establecido, añade el impulso y luego asígnale false.

Pulsa «Jugar»: las flechas impulsan de manera uniforme y cada pulsación de la barra espaciadora hace que el trineo salte. Después, pulsa «Comprobar».

Pruébalo tú mismo

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

Todas las lecciones de Física y jugabilidad

Practica por tu cuenta: Playground de Unity