Ввод — Input System и legacy Input
Клавиатура, мышь, геймпад и тач — два пути и почему стоит идти новым.
В Unity сейчас сосуществуют две системы ввода. Legacy Input класс — старый и простой. Input System
package — новый, мощный и рекомендованный для новых проектов.
Legacy Input — быстрый старт
Класс Input доступен из коробки. Опрашивается каждый кадр в Update:
private void Update() {
float h = Input.GetAxis("Horizontal"); // -1..1, левый стик/A-D/стрелки
float v = Input.GetAxis("Vertical");
if (Input.GetButtonDown("Jump")) {
// пробел был нажат в этом кадре
}
if (Input.GetMouseButton(0)) {
// ЛКМ удерживается
}
Vector2 mouseDelta = new Vector2(
Input.GetAxis("Mouse X"),
Input.GetAxis("Mouse Y")
);
}
Кнопки и оси определяются в Edit → Project Settings → Input Manager. Это словарь со значениями по умолчанию: “Horizontal”, “Vertical”, “Jump”, “Fire1”, “Mouse X” и так далее.
В Unity 6.3 LTS legacy Input Manager официально помечен deprecated с предупреждением в редакторе. API ещё работает, но удалят в одной из будущих major-версий. Используйте legacy только для быстрых прототипов или поддержки старых проектов. В новом коде — Input System.
Input System — современный путь
Input System — это пакет (устанавливается через Package Manager). Главные идеи:
- Actions, а не клавиши. Вы описываете действия (“Move”, “Jump”, “Shoot”) и привязываете к ним физические кнопки/оси/жесты. Один action — много привязок.
- Композитные привязки. “WASD” = композит из 4 клавиш, который возвращает
Vector2. - Контрольные схемы. “Keyboard & Mouse” vs “Gamepad” — автоматическое переключение, разные привязки.
- Callbacks, не polling. Подписываетесь на
performed,started,canceled.
Action Asset
В Project — Create → Input Actions. Открывается визуальный редактор: создаёте Action Map (например, “Player”), внутри — actions, и для каждого — bindings.
После настройки Unity сгенерирует C# класс (через “Generate C# Class” в инспекторе), которым удобно пользоваться:
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerController : MonoBehaviour
{
private PlayerControls _controls; // сгенерированный класс
private Vector2 _moveInput;
private void Awake() {
_controls = new PlayerControls();
_controls.Player.Move.performed += ctx => _moveInput = ctx.ReadValue<Vector2>();
_controls.Player.Move.canceled += _ => _moveInput = Vector2.zero;
_controls.Player.Jump.performed += _ => TryJump();
}
private void OnEnable() => _controls.Enable();
private void OnDisable() => _controls.Disable();
private void Update() {
var move = new Vector3(_moveInput.x, 0, _moveInput.y);
transform.Translate(move * 5f * Time.deltaTime, Space.Self);
}
private void TryJump() { /* ... */ }
}
Можно обойтись без ручного кода: вешаете компонент PlayerInput на GameObject, указываете Action
Asset, и связываете actions с вашими методами через UnityEvents в Inspector. Хорошо для прототипов
и кооперативной локалки (легко привязать второго игрока к второму геймпаду).
Поворот камеры мышью
Классическая задача: повернуть голову игрока за курсором. Pattern с Input System:
public class MouseLook : MonoBehaviour
{
[SerializeField] private float sensitivity = 0.1f;
[SerializeField] private Transform cameraPivot;
private float _pitch;
private float _yaw;
private Vector2 _lookInput;
private void Awake() {
Cursor.lockState = CursorLockMode.Locked; // спрятать и заблокировать
Cursor.visible = false;
}
public void OnLook(InputAction.CallbackContext ctx) {
_lookInput = ctx.ReadValue<Vector2>();
}
private void Update() {
_yaw += _lookInput.x * sensitivity;
_pitch -= _lookInput.y * sensitivity;
_pitch = Mathf.Clamp(_pitch, -85f, 85f);
transform.localRotation = Quaternion.Euler(0, _yaw, 0);
cameraPivot.localRotation = Quaternion.Euler(_pitch, 0, 0);
}
}
Важная деталь: pitch (вертикаль) применяется к дочернему объекту-камере, yaw (горизонталь) — к телу игрока. Это разделение упрощает физику: коллайдер игрока не наклоняется при взгляде вверх-вниз.
Geometry Raycast: “куда смотрит игрок”
Стрельба, выбор предмета, click-to-move — всё это построено на raycast. Луч из точки в направлении, ищет первое пересечение с коллайдером:
private void Shoot() {
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out RaycastHit hit, maxDistance: 100f)) {
Debug.Log($"Попали в {hit.collider.name} на расстоянии {hit.distance:F2}");
if (hit.collider.TryGetComponent<Enemy>(out var enemy)) {
enemy.TakeDamage(10);
}
}
}
Camera.main.ScreenPointToRay — стандартный приём перевести позицию курсора в луч из камеры. Для
FPS можно проще: transform.forward от камеры.
В следующем разделе — физика: как Rigidbody и Collider взаимодействуют между собой и с вашими скриптами.