El resumen de una línea#
Input y lógica en Update. Física (Rigidbody) en FixedUpdate. Cámara en LateUpdate. Si te quedas solo con esto, ya evitas el 90% de los problemas.
Por qué existen tres#
El problema de fondo es el tiempo. Update se llama una vez por fotograma, y los fotogramas no duran lo mismo: en un PC potente puede haber 240 por segundo y en un móvil 30. Si mueves algo sumando una cantidad fija por fotograma, se movería a distinta velocidad en cada máquina.
Por eso hay dos ritmos distintos:
Update | FixedUpdate | LateUpdate | |
|---|---|---|---|
| Frecuencia | 1 vez por fotograma (variable) | A intervalos fijos (0,02 s) | 1 vez por fotograma, al final |
| Depende de los FPS | Sí | No | Sí |
| Delta de tiempo | Time.deltaTime | Time.fixedDeltaTime | Time.deltaTime |
| Para qué | Input, lógica, temporizadores | Rigidbody, fuerzas, física | Cámara, seguir objetos |
| Puede correr varias veces por frame | No | Sí (si el frame es lento) | No |
FixedUpdate puede ejecutarse varias veces en un mismo fotograma (o ninguna). Si tu frame tarda 0,1 s y el paso fijo es 0,02 s, Unity ejecutará FixedUpdate cinco veces seguidas antes del siguiente Update para "ponerse al día" con la física. Por eso leer input con GetKeyDown dentro de FixedUpdate puede perder pulsaciones: léelo en Update.
Time.deltaTime: la pieza clave#
Para que el movimiento sea independiente de los FPS, multiplica por el tiempo transcurrido:
public float velocidad = 5f;
void Update()
{
// ❌ MAL: más rápido cuantos más FPS
// transform.position += Vector3.right * velocidad;
// ✅ BIEN: misma velocidad en cualquier máquina
transform.position += Vector3.right * velocidad * Time.deltaTime;
}velocidad * Time.deltaTime convierte "unidades por fotograma" en "unidades por segundo". Piensa siempre en velocidades por segundo y multiplica por deltaTime.
Por qué la cámara va en LateUpdate#
Si la cámara sigue al jugador y actualizas su posición en Update, puede ejecutarse antes de que el jugador se haya movido ese fotograma, provocando un tirón. LateUpdate corre después de todos los Update, así que el jugador ya está en su sitio final cuando la cámara lo copia.
void LateUpdate()
{
transform.position = objetivo.position + offset;
}Coste y estabilidad#
Qué usar en cada caso#
- ¿Tocas un Rigidbody o aplicas fuerzas? →
FixedUpdate - ¿Lees input o ejecutas lógica de juego? →
Update - ¿Mueves la cámara o algo que sigue a otro objeto? →
LateUpdate - ¿Necesitas algo cada X segundos, no cada frame? → una corrutina, no un Update
Errores frecuentes#
- Leer
Input.GetKeyDownenFixedUpdate(pierde pulsaciones). Léelo enUpdatey guarda un flag para consumirlo enFixedUpdate. - Olvidar
Time.deltaTimeenUpdate(el juego va más rápido en PCs potentes). - Multiplicar por
Time.deltaTimedentro deFixedUpdatecuando en realidad queríasTime.fixedDeltaTime(aunque dentro deFixedUpdate,Time.deltaTimeya devuelve el paso fijo, así que suele ser indistinto).
Resumen#
Tres ritmos, una regla: física en FixedUpdate, todo lo demás en Update, cámara en LateUpdate, y multiplica por Time.deltaTime siempre que muevas algo por fotograma. Para profundizar en cuándo se llama cada uno, vuelve a El ciclo de vida de MonoBehaviour.