Движение объекта через код и Time.deltaTime
Заставим объект двигаться кодом. Здесь же разберём важнейшую формулу геймдева — почему движение умножают на Time.deltaTime.
Суть: чтобы двигать объект в Update, меняй
transform.positionили вызывайtransform.Translate. Скорость всегда умножай наTime.deltaTime— время прошлого кадра. Тогда объект движется одинаково при любом FPS.
Самое частое действие в играх — что-то двигать. В Unity объект двигают, меняя его transform.position. Но если просто прибавлять скорость каждый кадр, скорость будет зависеть от FPS: на 120 FPS объект улетит вдвое быстрее, чем на 60. Решение — Time.deltaTime.
Time.deltaTime — это время, прошедшее с прошлого кадра, в секундах. На 60 FPS это ~0.0166. Умножая скорость на него, ты переводишь «единиц в секунду» в «единиц за этот кадр». Итог: за секунду объект пройдёт одинаковый путь при любом FPS.
Как работает под капотом
Формула кадрового движения:
путь_за_кадр = скорость * Time.deltaTime
60 FPS: dt=0.0166, скорость=5 -> за кадр 0.083, за сек ~5.0
30 FPS: dt=0.0333, скорость=5 -> за кадр 0.166, за сек ~5.0
(тот же путь за секунду!)Для движения по направлению используют вектор. Например ввод «вправо-вверх» даёт направление (1, 1). Но у диагонали длина больше 1, и объект двигался бы по диагонали быстрее! Поэтому направление нормализуют — приводят к длине 1, чтобы скорость была одинаковой во все стороны.
using UnityEngine;
public class SimpleMover : MonoBehaviour
{
[SerializeField] private float speed = 5f;
void Update()
{
// направление по стрелкам (упрощённо)
float h = Input.GetAxisRaw("Horizontal");
float v = Input.GetAxisRaw("Vertical");
Vector2 dir = new Vector2(h, v).normalized; // длина = 1
transform.position += (Vector3)(dir * speed * Time.deltaTime);
}
}Эта математика языко-независима. Посчитаем движение по вектору с нормализацией на Python:
import math
def normalize(x, y):
length = math.hypot(x, y) # длина вектора
if length == 0:
return (0.0, 0.0)
return (x / length, y / length) # длина становится 1
speed = 5.0
dt = 1 / 60 # один кадр при 60 FPS
x, y = 0.0, 0.0
# Игрок жмёт вправо-вверх: направление (1, 1)
dx, dy = normalize(1, 1)
print(f"Нормализованное направление: ({dx:.3f}, {dy:.3f})")
for frame in range(60): # одна секунда
x += dx * speed * dt
y += dy * speed * dt
print(f"За секунду герой в точке ({x:.2f}, {y:.2f}), путь = {math.hypot(x, y):.2f}")Та же логика на Python ▶ — обрати внимание: путь за секунду равен ~5 (наша скорость), хотя двигались по диагонали. Это заслуга нормализации. Без неё диагональ была бы быстрее в ~1.41 раза.
Частые ошибки
- Забыть Time.deltaTime. Тогда скорость зависит от FPS: на мощном ПК герой носится, на слабом ползёт. Классический баг новичка.
- Не нормализовать диагональ. Объект двигается по диагонали быстрее, чем по прямой — игроки это чувствуют.
- Двигать физический объект через transform.position. Если у объекта есть Rigidbody2D, прямой сдвиг position конфликтует с физикой. Об этом — в разделе про физику.
Best practices
- Всегда:
скорость * Time.deltaTimeв Update для любого плавного движения. - Нормализуй вектор направления перед умножением на скорость.
- Скорость держи в
[SerializeField]-поле, чтобы подбирать её мышкой.
Итоги: объект двигают, меняя transform.position в Update. Скорость умножают на Time.deltaTime, чтобы движение не зависело от FPS, и нормализуют направление, чтобы диагональ не была быстрее. Эта формула — фундамент любого движения в играх.
Кинематика против физики движения
Важно с самого начала различать два способа двигать объект. Первый — кинематический: ты напрямую задаёшь позицию через transform.position, как мы делали выше. Объект окажется ровно там, куда ты сказал, мгновенно и точно — но он игнорирует физику: пройдёт сквозь стену, не оттолкнётся, не упадёт. Второй — физический: ты задаёшь скорость или силу телу с Rigidbody, а движок сам двигает его с учётом столкновений и гравитации. Точного контроля меньше, зато всё взаимодействует по-настоящему. Правило простое: если у объекта есть Rigidbody2D, двигай его через физику, а не через transform.position — иначе два механизма начнут спорить за позицию и объект задёргается. К физическому движению мы перейдём в следующем разделе, а пока запомни эту развилку как одну из главных в геймдеве.