4、输入系统入门:旧版Input Manager、获取键盘/鼠标输入、Axis虚拟轴、Input.GetKey与Input.GetButton
好,咱们今天来聊聊Unity的输入系统。说实话,这是每个做游戏的人绕不开的第一道坎。你想想看,玩家怎么跟你的游戏世界互动?不就是靠键盘、鼠标、手柄这些外设嘛。
Unity提供了两套输入方案:一套是经典的旧版Input Manager,另一套是后来推出的新版Input System Package。我个人习惯,在快速原型或者小项目里,还是用旧版居多——它简单、直接,不用折腾包管理。今天咱们就先把旧版吃透。
4.1 旧版Input Manager长什么样?
打开Unity编辑器,菜单栏选 Edit → Project Settings → Input Manager。你会看到一大串列表,里面全是预设好的虚拟轴(Axes)。
嗯,这里要注意:这些轴不是物理轴,而是逻辑轴。说白了,就是把键盘上的W键、手柄的左摇杆、鼠标的移动,统统映射到一个叫“Vertical”或者“Horizontal”的名字上。你写代码的时候不用管玩家按的是键盘还是手柄,直接读轴的名字就行。
我刚开始做项目时,总觉得这玩意儿可有可无。直到有一次,我写死了Input.GetKey(KeyCode.W)来让角色前进,结果测试时发现手柄玩家根本动不了……从那以后,我再也不敢跳过Input Manager的配置了。
4.2 获取键盘输入:Input.GetKey
这是最原始的方式。你想检测某个键是否被按下,就用它。
// 检测W键是否被按住
if (Input.GetKey(KeyCode.W))
{
Debug.Log("W键正在被按住");
}
// 检测W键按下的那一帧
if (Input.GetKeyDown(KeyCode.W))
{
Debug.Log("W键刚刚被按下");
}
// 检测W键松开的那一帧
if (Input.GetKeyUp(KeyCode.W))
{
Debug.Log("W键刚刚被松开");
}
三种状态:GetKey(按住)、GetKeyDown(按下瞬间)、GetKeyUp(松开瞬间)。
4.3 获取鼠标输入
鼠标输入分两类:按键和移动。
鼠标按键:
// 左键
if (Input.GetMouseButton(0))
{
Debug.Log("左键按住");
}
// 右键
if (Input.GetMouseButtonDown(1))
{
Debug.Log("右键按下");
}
// 中键
if (Input.GetMouseButtonUp(2))
{
Debug.Log("中键松开");
}
参数0、1、2分别对应左键、右键、中键。这个顺序别记反了,我见过有人把1当成左键,结果右键开火……
鼠标移动:
float mouseX = Input.GetAxis("Mouse X");
float mouseY = Input.GetAxis("Mouse Y");
// 通常用来控制视角旋转
transform.Rotate(Vector3.up * mouseX * sensitivity);
这里返回的是增量值,不是绝对坐标。说白了,就是这一帧鼠标移动了多少像素。你把它乘上一个灵敏度系数,就能控制镜头转动速度。
4.4 Axis虚拟轴:Input.GetAxis
这是旧版Input Manager的精髓。你想想看,如果每个按键都要单独写GetKey,那代码得多乱?虚拟轴就是来解决这个问题的。
Unity默认提供了几个常用轴:
| 轴名称 | 默认按键 | 用途 |
|---|---|---|
| Horizontal | A/D 或 左/右方向键 | 水平移动 |
| Vertical | W/S 或 上/下方向键 | 垂直移动 |
| Mouse X | 鼠标水平移动 | 视角水平旋转 |
| Mouse Y | 鼠标垂直移动 | 视角垂直旋转 |
| Fire1 | 左Ctrl 或 鼠标左键 | 开火/交互 |
| Jump | 空格键 | 跳跃 |
用法很简单:
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
Vector3 move = new Vector3(h, 0, v);
transform.Translate(move * speed * Time.deltaTime);
这里有个细节:GetAxis返回的是-1到1之间的浮点数。你按A键,它慢慢滑到-1;你松开,它慢慢滑回0。这种平滑过渡让移动手感很自然。
Input.GetAxisRaw。它只返回-1、0、1三个值,没有平滑过渡。我在做平台跳跃游戏时,跳跃用GetAxisRaw,移动用GetAxis,手感刚刚好。
4.5 Input.GetButton 与 Input.GetButtonDown
跟GetKey类似,但GetButton是绑定到虚拟轴名字上的。说白了,它让你用逻辑名字代替物理按键。
// 检测Fire1轴是否被按住
if (Input.GetButton("Fire1"))
{
Debug.Log("开火中...");
}
// 检测Fire1轴按下的那一帧
if (Input.GetButtonDown("Jump"))
{
Debug.Log("跳跃!");
}
// 检测Fire1轴松开的那一帧
if (Input.GetButtonUp("Fire1"))
{
Debug.Log("停止开火");
}
这样做的好处是:如果以后你想把跳跃键从空格改成手柄的A键,只需要在Input Manager里改映射,代码一行都不用动。
4.6 实战:一个简单的角色移动脚本
咱们把今天学的串起来,写一个完整的角色控制脚本:
using UnityEngine;
public class SimplePlayerController : MonoBehaviour
{
public float moveSpeed = 5f;
public float rotateSpeed = 100f;
void Update()
{
// 移动:用虚拟轴
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
Vector3 move = new Vector3(h, 0, v);
transform.Translate(move * moveSpeed * Time.deltaTime, Space.World);
// 旋转:用鼠标
float mouseX = Input.GetAxis("Mouse X");
transform.Rotate(Vector3.up * mouseX * rotateSpeed * Time.deltaTime);
// 跳跃:用GetButtonDown
if (Input.GetButtonDown("Jump"))
{
GetComponent<Rigidbody>().AddForce(Vector3.up * 5f, ForceMode.Impulse);
}
// 开火:用GetButton
if (Input.GetButton("Fire1"))
{
Debug.Log("开火中...");
}
}
}
这个脚本虽然简单,但涵盖了今天讲的所有核心内容。你把它挂到角色身上,就能用WASD移动、鼠标转视角、空格跳跃、左键开火。
4.7 避坑指南
最后,分享几个我踩过的坑:
- Input.GetAxis 放在 FixedUpdate 里? 别。FixedUpdate的调用频率跟物理帧走,不稳定。输入检测永远放Update里。
- 鼠标锁定: 做FPS游戏时,记得用
Cursor.lockState = CursorLockMode.Locked把鼠标锁在屏幕中心。不然鼠标一移出窗口,视角就乱跳。 - 多平台兼容: 如果你打算发布到手机或主机,旧版Input Manager可能不够用。那时候就得考虑新版Input System了。不过那是后面章节的事,今天先把基础打牢。
好,今天就到这儿。下一章咱们会深入Input Manager的配置面板,看看怎么自定义轴、怎么处理多按键冲突。到时候你会发现,原来输入系统也可以玩出花来。