如何使Delta[鼠标]等效Input.GetAxis("Mouse X/Y")且不影响控制器运作
解决Unity新输入系统鼠标与控制器视角灵敏度差异问题
问题背景
我正在开发一款支持键鼠与控制器双操控的第一人称游戏,之前用Input.GetAxis("Mouse X/Y")实现视角控制。改用Unity新输入系统后,将鼠标Delta和控制器右摇杆绑定到同一个Vector2类型的Look输入动作,出现了严重的灵敏度差异——同一灵敏度下,要么鼠标操作过于灵敏难以控制,要么控制器摇杆移动视角太慢。我需要让新输入系统的鼠标输入效果等效于旧系统的Input.GetAxis("Mouse X/Y")(取值范围-1到1),同时保证控制器操作不会过慢。
当前输入处理代码如下:
// 获取视角输入 var CameraXY = inputActions.Player.Look.ReadValue<Vector2>(); // 处理视角移动 if (cameraCanMove) { yaw = transform.localEulerAngles.y + CameraXY.x * mouseSensitivity; if (!invertCamera) { pitch -= mouseSensitivity * CameraXY.y; } else { // 反转Y轴 pitch += mouseSensitivity * CameraXY.y; } // 限制俯仰角度 pitch = Mathf.Clamp(pitch, -maxLookAngle, maxLookAngle); transform.localEulerAngles = new Vector3(0, yaw, 0); playerCamera.transform.localEulerAngles = new Vector3(pitch, 0, 0); }
补充:尝试过对输入值做归一化处理,但无法得到和Input.GetAxis一致的数值。
核心解决思路
新输入系统中,鼠标Delta返回的是帧内像素位移量(比如鼠标移动10像素就返回10左右),而旧系统Input.GetAxis("Mouse X/Y")返回的是基于帧率归一化后的相对值(通常在-1到1之间),控制器摇杆返回的则是原生-1到1的轴值。所以必须区分鼠标和控制器输入,分别应用不同的灵敏度缩放逻辑,不能用同一套参数处理。
方案1:拆分输入动作(推荐)
不要把鼠标和摇杆绑定到同一个动作,而是分开创建两个独立输入动作:
MouseLook:绑定鼠标Delta的X/Y轴GamepadLook:绑定控制器右摇杆的X/Y轴
这样可以直接区分输入源,逻辑更清晰。处理代码如下:
// 分别定义鼠标和控制器的灵敏度参数,方便独立调试 [SerializeField] private float mouseSensitivity = 2f; [SerializeField] private float gamepadSensitivity = 15f; private void Update() { if (!cameraCanMove) return; Vector2 finalLookInput = Vector2.zero; // 处理鼠标输入:转换为旧Input.GetAxis等效范围 var mouseInput = inputActions.Player.MouseLook.ReadValue<Vector2>(); // 用屏幕宽度做参考缩放,模拟旧系统的归一化效果,可根据手感调整除数 finalLookInput += new Vector2( mouseInput.x / Screen.width * mouseSensitivity, mouseInput.y / Screen.width * mouseSensitivity ); // 处理控制器输入:直接用摇杆的-1到1值,乘以更高灵敏度并做时间归一化 var gamepadInput = inputActions.Player.GamepadLook.ReadValue<Vector2>(); finalLookInput += gamepadInput * gamepadSensitivity * Time.deltaTime; // 应用视角旋转 yaw += finalLookInput.x; pitch = invertCamera ? pitch + finalLookInput.y : pitch - finalLookInput.y; pitch = Mathf.Clamp(pitch, -maxLookAngle, maxLookAngle); transform.localEulerAngles = new Vector3(0, yaw, 0); playerCamera.transform.localEulerAngles = new Vector3(pitch, 0, 0); }
方案2:共用动作时区分输入源
如果不想拆分动作,可以通过检查输入动作的活跃设备类型来判断当前是鼠标还是控制器输入:
[SerializeField] private float mouseSensitivity = 2f; [SerializeField] private float gamepadSensitivity = 15f; private void Update() { if (!cameraCanMove) return; var lookAction = inputActions.Player.Look; Vector2 rawInput = lookAction.ReadValue<Vector2>(); Vector2 finalLookInput = Vector2.zero; // 判断当前输入源是否为鼠标 bool isMouseInput = lookAction.activeControl?.device is Mouse; if (isMouseInput) { // 鼠标输入转换为旧系统等效范围 finalLookInput = new Vector2( rawInput.x / Screen.width * mouseSensitivity, rawInput.y / Screen.width * mouseSensitivity ); } else { // 控制器输入直接放大灵敏度并做时间归一化 finalLookInput = rawInput * gamepadSensitivity * Time.deltaTime; } // 应用视角旋转 yaw += finalLookInput.x; pitch = invertCamera ? pitch + finalLookInput.y : pitch - finalLookInput.y; pitch = Mathf.Clamp(pitch, -maxLookAngle, maxLookAngle); transform.localEulerAngles = new Vector3(0, yaw, 0); playerCamera.transform.localEulerAngles = new Vector3(pitch, 0, 0); }
关键细节说明
- 鼠标输入缩放逻辑:旧系统
Input.GetAxis的数值是Unity内部根据帧率和鼠标速度归一化的,这里用Screen.width作为参考除数,你可以根据实际手感调整(比如换成固定值1000,或者Screen.height)。 - 控制器输入的时间归一化:摇杆是持续输入,必须乘以
Time.deltaTime保证不同帧率下移动速度一致;而鼠标Delta本身是帧内位移,不需要乘Time.deltaTime。 - 独立灵敏度参数:给鼠标和控制器各自的灵敏度滑块,方便快速调试到符合玩家习惯的手感。
内容的提问来源于stack exchange,提问作者StickKai
相关产品推荐
相关产品推荐

