Menu
CoddyTech

FixedUpdate для физики

Часть раздела Физика и игровой процесс путешествия по Unity на Coddy. Урок 4 из 63.

Unity перемещает тела фиксированными шагами физики по 0.02 секунды (Time.fixedDeltaTime), 50 раз в секунду, независимо от частоты кадров. FixedUpdate() выполняется непосредственно перед каждым шагом. Update() выполняется один раз за каждый отрисованный кадр, а таких кадров может быть 30, 60 или 144 в секунду: при 144 кадрах в секунду на большинстве кадров шаг физики вообще не выполняется, а на медленном компьютере в одном кадре могут уместиться два шага.

Отсюда следуют два правила. Сила, добавленная в Update(), добавляется один раз за кадр, поэтому более быстрый компьютер толкает сильнее: силы, действующие на протяжении времени, добавляй в FixedUpdate(). А GetKeyDown имеет значение true только в течение одного кадра; если в этот кадр шаг физики не выполняется, FixedUpdate() его не увидит, и нажатие будет потеряно. Поэтому считывай нажатия в Update(), сохраняй их в bool и обрабатывай в FixedUpdate(). Эту лодку толкает постоянный ветер, а при щелчке она делает рывок вбок:

private bool dashQueued;

void Update()
{
    if (Input.GetMouseButtonDown(0))
    {
        dashQueued = true;   // запомнить нажатие
    }
}

void FixedUpdate()
{
    rb.AddForce(Vector3.forward * wind);   // постоянный толчок на каждом шаге
    if (dashQueued)
    {
        rb.AddForce(Vector3.right * 4f, ForceMode.Impulse);
        dashQueued = false;   // одно нажатие — один рывок
    }
}

Важно сбросить значение bool после его использования: если оставить true, лодка будет делать рывок на каждом шаге. Одиночный импульс также можно добавить прямо из Update(), как это было сделано с прыжком лягушки; bool позволяет держать все толчки в одном месте, рядом с силами, с которыми он работает. Удерживаемые клавиши (GetKey, GetAxis) описывают состояние, а не отдельный момент, поэтому FixedUpdate() может считывать их напрямую. Внутри FixedUpdate() Time.deltaTime возвращает значение 0.02 для этого шага.

challenge icon

Задание

Легко

У саней на замёрзшем озере обе задачи выполняются не в тех методах. Стрелки толкают их в Update(), поэтому на более быстрых компьютерах они толкаются сильнее. Нажатие пробела заставляет их подпрыгнуть с импульсом в FixedUpdate(), поэтому некоторые нажатия ничего не делают.

  • Перенеси обработку стрелок в FixedUpdate().
  • Считывай нажатие пробела в Update() в переменную типа bool с именем hopPressed; в FixedUpdate() подпрыгивай, если она установлена, а затем сбрасывай её.

Нажми Play и попробуй оба варианта, затем нажми Check.

Попробуйте сами

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);
        }
    }
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Физика и игровой процесс