Input System mới
Assets/
Scripts/
Settings/
thiết lập dự án
đã có sẵnbài này thêmbài này thay thế
Ba script bạn đã viết vẫn gọi thẳng Input: PlayerMovement đọc GetAxisRaw, CharacterSwitcher đọc phím số, SkillCaster đọc Q, E, R. Cả ba đều dính chết vào bàn phím — và đó là vấn đề, vì tab 05 sẽ đưa cái này lên điện thoại.
Input System cho bạn định nghĩa hành động một lần rồi gán phím, tay cầm và cảm ứng vào đó. Học xong bài này, không script gameplay nào của bạn còn biết người chơi đang cầm thiết bị gì.
Thiết bị bên trái, một file action ở giữa, code gameplay của bạn bên phải.
Cài và chuyển sang dùng
- 1
Package Manager → Input System → Install. Unity hỏi khởi động lại; chọn có.
- 2
→ chọn Both trong lúc chuyển đổi.
- 3
Project: , đặt tên PlayerControls, bấm đúp để mở trình soạn.
- 4
Tick Generate C# Class rồi bấm Apply — Unity tự sinh ra class bọc sẵn.
Dựng bản đồ hành động
- 1
Thêm một Action Map tên Gameplay.
- 2
Action Move → Action Type Value → Control Type Vector2. Thêm binding kiểu 2D Vector Composite: W/A/S/D. Thêm binding nữa: cần trái tay cầm.
- 3
Action Look → Value → Vector2 → gán Mouse Delta và cần phải tay cầm.
- 4
Action Jump và Attack → Action Type Button → gán Space / nút South và chuột trái / nút West.
- 5
Action Skill1 / Skill2 / Skill3 → Button → gán Q, E, R. Chúng thay cho các phím mà SkillCaster đang tự đọc.
- 6
Action SwapCharacter → Value / Axis → gán phím 1, 2, 3. Chúng thay cho phần CharacterSwitcher đang tự đọc.
Đọc trong code
using UnityEngine;
using UnityEngine.InputSystem;
public class InputRouter : MonoBehaviour
{
//do class sinh tự động điền vào
private PlayerControls controls;
public Vector2 Move { get; private set; }
public Vector2 Look { get; private set; }
public bool JumpPressed { get; private set; }
void Awake()
{
controls = new PlayerControls();
controls.Gameplay.Move.performed += ctx => Move = ctx.ReadValue<Vector2>();
controls.Gameplay.Move.canceled += ctx => Move = Vector2.zero; // đừng bao giờ quên dòng này
controls.Gameplay.Look.performed += ctx => Look = ctx.ReadValue<Vector2>();
controls.Gameplay.Look.canceled += ctx => Look = Vector2.zero;
controls.Gameplay.Jump.performed += ctx => JumpPressed = true;
controls.Gameplay.Attack.performed += ctx => GetComponent<SkillCaster>().TryCast(0);
}
void OnEnable() => controls.Enable(); // quên là không nhận phím
void OnDisable() => controls.Disable();
void LateUpdate() => JumpPressed = false; // cờ chỉ đúng trong 1 khung hình
}performed chạy khi bắt đầu hoặc thay đổi; canceled chạy khi thả ra. Quên canceled là nhân vật đi mãi không dừng.
Move là Vector2 (x, y). Trong 3D bạn ánh xạ thành (x, 0, y) — trục y của cần gạt thành trục Z của thế giới.
Một action map thứ hai tên UI có thể bật lên khi Gameplay bị tắt — đó là cách menu tạm dừng chặn nhân vật di chuyển.
Loại bỏ ba chỗ đọc phím cũ
Đây là phần dọn dẹp làm cho cả tab này đáng công. Xoá mọi Input.GetAxis, Input.GetKey, Input.GetMouseButton trong dự án và cho chúng đi qua InputRouter.
// 1 — PlayerMovement.cs
- float h = Input.GetAxisRaw("Horizontal");
- float v = Input.GetAxisRaw("Vertical");
- Vector3 input = new Vector3(h, 0f, v).normalized;
+ Vector3 input = new Vector3(router.Move.x, 0f, router.Move.y).normalized;
// 2 — CharacterSwitcher.cs
- for (int i = 0; i < characters.Count && i < 9; i++)
- if (Input.GetKeyDown(KeyCode.Alpha1 + i)) Select(i);
+ // in InputRouter.Awake:
+ controls.Gameplay.SwapCharacter.performed += c => switcher.Select((int)c.ReadValue<float>() - 1);
// 3 — SkillCaster.cs
- for (int i = 0; i < skills.Count && i < keys.Length; i++)
- if (Input.GetKeyDown(keys[i])) TryCast(i);
+ // in InputRouter.Awake:
+ controls.Gameplay.Skill1.performed += _ => caster.TryCast(0);
+ controls.Gameplay.Skill2.performed += _ => caster.TryCast(1);
+ controls.Gameplay.Skill3.performed += _ => caster.TryCast(2);Dùng trong script di chuyển
[SerializeField] private InputRouter input;
void Update()
{
Vector3 dir = new Vector3(input.Move.x, 0f, input.Move.y);
//phần còn lại y hệt script cũ
}✓ PlayerInput component
Kéo thả, ít code
✓ Generated C# class
Class tự sinh