Урок 4 из 8 · 25 мин · обновлено
Движение и управление: ввод, физика и камера
Как прочитать нажатия клавиш через Input System, двигать объект физикой через Rigidbody, чем Update отличается от FixedUpdate и как заставить камеру следовать за игроком.
Rigidbody: подключаем физику
Можно двигать шар, меняя transform.position, но тогда он будет проходить сквозь стены и не будет катиться. Пусть лучше движением займётся физика.
Выберите Player и добавьте компонент Rigidbody (Add Component → Physics → Rigidbody). Нажмите Play: если приподнять шар над полом, он упадёт и остановится. Сферический коллайдер у шара уже есть, у пола тоже — поэтому шар не проваливается.
Главные настройки Rigidbody:
- Mass — масса: тяжёлый шар труднее разогнать;
- Linear Damping — сопротивление: чем больше, тем быстрее шар останавливается;
- Use Gravity — подчиняется ли объект гравитации.
Ввод: Input System
В проектах Unity 6 нажатия читает Input System. В шаблоне уже настроены действия: Move — движение (WASD, стрелки, левый стик геймпада), Jump — прыжок (пробел, кнопка геймпада) и другие. Удобно: один и тот же код работает и с клавиатурой, и с геймпадом.
Действие Move выдаёт Vector2 — пару чисел (x, y): x — вправо-влево, y — вперёд-назад. Нажата D — (1, 0), нажата W — (0, 1), ничего не нажато — (0, 0).
В старых уроках из интернета встречается Input.GetAxis("Horizontal"). Это прежняя система ввода: в новых проектах она выключена, и такой код выдаст ошибку.
Скрипт управления
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerController : MonoBehaviour
{
[SerializeField] private float speed = 10f;
private Rigidbody rb;
private InputAction moveAction;
private Vector2 moveInput;
void Start()
{
rb = GetComponent<Rigidbody>();
moveAction = InputSystem.actions.FindAction("Move");
}
void Update()
{
moveInput = moveAction.ReadValue<Vector2>();
}
void FixedUpdate()
{
Vector3 force = new Vector3(moveInput.x, 0, moveInput.y);
rb.AddForce(force * speed);
}
}
Разберём:
GetComponent<Rigidbody>()находит компонент Rigidbody на этом же объекте. Ищем один раз в Start и запоминаем в полеrb;InputSystem.actions.FindAction("Move")находит действие по имени;- в Update читаем ввод — каждый кадр;
- в FixedUpdate толкаем шар. Этот метод вызывается с постоянным шагом физики, по умолчанию 50 раз в секунду, независимо от числа кадров;
Vector3— три числа (x, y, z). Двумерный ввод превращаем в трёхмерную силу: y ввода становится осью z, «вперёд», а вверх не толкаем;AddForceтолкает шар, а дальше физика сама разгоняет и тормозит его.
Повесьте скрипт на Player, нажмите Play и покатайте шар клавишами.
Камера за игроком
Шар укатывается за край экрана. Пусть камера следует за ним на постоянном расстоянии:
using UnityEngine;
public class CameraFollow : MonoBehaviour
{
[SerializeField] private Transform target;
private Vector3 offset;
void Start()
{
offset = transform.position - target.position;
}
void LateUpdate()
{
transform.position = target.position + offset;
}
}
Повесьте скрипт на Main Camera и перетащите Player из Hierarchy в поле Target в Inspector. В Start камера запоминает, где она стоит относительно игрока. В LateUpdate, который вызывается после всех Update, она переезжает на то же расстояние от нового положения игрока.
Попробуйте сами. Добавьте прыжок: по действию Jump шар подпрыгивает. Прыгать можно только с земли, а не в воздухе.
Решение
Добавьте в PlayerController поля и код в Start и Update:
[SerializeField] private float jumpForce = 5f;
private InputAction jumpAction;
void Start()
{
rb = GetComponent<Rigidbody>();
moveAction = InputSystem.actions.FindAction("Move");
jumpAction = InputSystem.actions.FindAction("Jump");
}
void Update()
{
moveInput = moveAction.ReadValue<Vector2>();
bool onGround = Mathf.Abs(rb.linearVelocity.y) < 0.01f;
if (jumpAction.WasPressedThisFrame() && onGround)
{
rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
}
}
WasPressedThisFrame() срабатывает один раз в момент нажатия. Без этого шар прыгал бы каждый кадр, пока клавиша зажата. ForceMode.Impulse даёт мгновенный толчок, а не постепенный разгон.
Проверка «на земле» простая: если шар почти не движется по вертикали, он не в полёте. В настоящих играх землю проверяют точнее — лучом вниз, но для начала хватит.
Мини-тест: проверьте себя
Закрепите урок: несколько вопросов, разбор ответов — в конце.
-
Что произойдёт с шаром, если добавить ему компонент Rigidbody и нажать Play?
Rigidbody подключает объект к физическому движку. Гравитация включена по умолчанию, поэтому шар падает, пока не встретит коллайдер пола.
-
В каком методе правильно прикладывать силы к Rigidbody?
FixedUpdate вызывается с постоянным шагом физики, независимо от числа кадров. Поэтому силы в нём действуют одинаково на любом компьютере.
-
Что вернёт moveAction.ReadValue<Vector2>(), если игрок держит клавишу D?
Move отдаёт направление: x — вправо-влево, y — вперёд-назад. Клавиша D — вправо, поэтому x = 1, y = 0.
-
Почему камеру двигают в LateUpdate, а не в Update?
Если двигать камеру в Update, она может сработать раньше игрока и отставать на кадр — картинка дрожит. LateUpdate гарантирует, что игрок уже на месте.