Menu
CoddyTech

FixedUpdate для физики

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

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

Задание

Легко

Размести две задачи саней в правильных методах.

  1. Перемести два блока if со стрелками из Update() в FixedUpdate().
  2. Добавь private bool hopPressed;. В Update() присвой ему значение true при нажатии Input.GetKeyDown(KeyCode.Space).
  3. В FixedUpdate(), когда установлено значение hopPressed, добавь импульс, а затем присвой ему значение false.

Нажми «Играть»: стрелки будут равномерно толкать сани, а каждое нажатие пробела будет заставлять их подпрыгивать. Затем нажми «Проверить».

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

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

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

Потренируйтесь самостоятельно: Песочница Unity