Метод FixedUpdate в Unity C# — фиксированное обновление для физики
FixedUpdate в Unity — обновление с постоянным интервалом, созданное для физики. В отличие от Update, оно вызывается с одинаковой частотой независимо от FPS: по умолчанию 50 раз в секунду, раз в 0.02 секунды.
Как вызывается
- Интервал задаёт
Time.fixedDeltaTime— по умолчанию 0.02 секунды (50 вызовов в секунду). Меняется в коде или в настройках проекта (параметр Fixed Timestep). - Вызывается независимо от кадров: при 120 FPS FixedUpdate отработает те же 50 раз в секунду, что и при 30.
- За один кадр может вызваться несколько раз (если кадр долгий) или ни разу (если кадр короткий).
- Вызывается, пока компонент включён.
Зачем нужна отдельная частота
Симуляция физики должна получать одинаковый шаг времени. Если считать физику в Update, результат будет зависеть от FPS: на 120 кадрах тело получит вдвое больше итераций, чем на 60, и поведение разойдётся. FixedUpdate решает это — шаг физики всегда одинаков.
Пример: сила каждый физический шаг
using UnityEngine;
public class CarController : MonoBehaviour
{
public Rigidbody body;
public float force = 1500f;
void FixedUpdate()
{
// Сила применяется с постоянной частотой — поведение
// одинаково на 30 и на 144 FPS
if (Input.GetKey(KeyCode.W))
{
body.AddForce(Vector3.forward * force);
}
}
}
Пример: замедленное воспроизведение
FixedUpdate зависит от игрового времени. При Time.timeScale = 0.5 интервал в 0.02 секунды превращается в физические обновления раз в 2 реальные секунды — так работает слоу-мо. При паузе (timeScale = 0) FixedUpdate перестаёт вызываться совсем.
using UnityEngine;
public class SlowMotion : MonoBehaviour
{
void Update()
{
// Замедляем игру вдвое — физика тоже замедлится
if (Input.GetKeyDown(KeyCode.T))
{
Time.timeScale = 0.5f;
Debug.Log("Замедление: " + Time.timeScale);
}
// Пауза останавливает FixedUpdate полностью
if (Input.GetKeyDown(KeyCode.P))
{
Time.timeScale = 0f;
}
}
}
FixedUpdate или Update
| Задача | Где |
|---|---|
| Силы, импульсы, работу с Rigidbody | FixedUpdate |
| Проверки коллизий, рейкасты по физике | FixedUpdate |
| transform-движение без физики | Update |
| Ввод с клавиатуры и мыши | Update (события ввода привязаны к кадрам) |
| Логика, не привязанная к физике | Update |
Практический приём: состояние ввода читают в Update (нажата ли кнопка сейчас), а применяют к физике в FixedUpdate — иначе быстрые нажатия между физическими шагами потеряются.
Чтение ввода внутри FixedUpdate
Вот ловушка, о которой забывают: события Input.GetKeyDown привязаны к кадрам. В FixedUpdate они могут вернуть false даже при нажатой кнопке — кадр был, а FixedUpdate в этот момент не выполнялся. Решение — кэшировать флаг в Update и применять его в FixedUpdate:
using UnityEngine;
public class Jump : MonoBehaviour
{
public Rigidbody body;
public float jumpForce = 7f;
private bool jumpPressed;
void Update()
{
// Фиксируем нажатие в кадровом потоке
if (Input.GetKeyDown(KeyCode.Space))
{
jumpPressed = true;
}
}
void FixedUpdate()
{
if (jumpPressed)
{
body.AddForce(Vector3.up * jumpForce);
jumpPressed = false;
}
}
}
Частые ошибки
1. Скорость движения через transform в FixedUpdate
transform.Translate в FixedUpdate двигает объект рывками — позиция обновляется 50 раз в секунду, а рендер каждый кадр. Для плавности физическое движение делают через Rigidbody.
2. Time.deltaTime вместо fixedDeltaTime
Внутри FixedUpdate обычный Time.deltaTime возвращает время физического шага (0.02), но для физических величин правильно ориентироваться на Time.fixedDeltaTime — это прямое указание, с каким шагом работает симуляция.
3. Забытая проверка enabled
FixedUpdate не вызывается у выключенного компонента — пригодится, когда нужно «заморозить» физику конкретного объекта.
4. Ожидание ввода без кэша
См. пример выше: ввод кэшируют в Update.