新Input Manager中键鼠与手柄的角色移动旋转控制优化问询
Unity新Input Manager键鼠与手柄控制优化方案
核心问题分析
你的代码目前没有区分键鼠离散输入和手柄模拟输入的特性:
- 移动方面:WASD/方向键是0或1的数字输入,直接用
AddForce会导致键鼠移动手感生硬,而手柄摇杆是0-1的平滑输入,适配当前逻辑没问题。 - 旋转方面:鼠标输入是每帧增量值(反映鼠标移动的距离),手柄摇杆是绝对值(当前摇杆的偏转程度),两者用同一套旋转速度逻辑,必然顾此失彼。
优化方案
1. 移动控制优化
改用Rigidbody.velocity控制移动(比AddForce更稳定),同时根据设备类型调整速度系数,避免键鼠移动过于突兀:
using UnityEngine; using UnityEngine.InputSystem; public class PlayerControllerBase : MonoBehaviour { [SerializeField] private PlayerConfig _playerConfig; [SerializeField] private Rigidbody _playerRb; // 新增:键鼠与手柄的速度系数区分 [SerializeField] private float _keyboardMoveMultiplier = 0.7f; [SerializeField] private float _gamepadMoveMultiplier = 1f; private Vector2 _moveInput; private InputDevice _currentInputDevice; private void Awake() { // 监听输入设备变更 InputSystem.onDeviceChange += OnDeviceChange; // 初始化当前设备 _currentInputDevice = Keyboard.current != null ? Keyboard.current : Gamepad.current; } private void OnDeviceChange(InputDevice device, InputDeviceChange change) { if (change == InputDeviceChange.Added) { if (device is Keyboard || device is Gamepad) { _currentInputDevice = device; } } } public void OnMove(InputAction.CallbackContext context) { _moveInput = context.ReadValue<Vector2>(); // 归一化输入,避免斜向移动速度过快 if (_moveInput.magnitude > 1) { _moveInput.Normalize(); } } private void FixedUpdate() { HandleMovement(); HandleRotation(); } private void HandleMovement() { float moveMultiplier = _currentInputDevice is Keyboard ? _keyboardMoveMultiplier : _gamepadMoveMultiplier; Vector3 moveDir = new Vector3(_moveInput.x, 0, _moveInput.y) * _playerConfig.PlayerSpeed * moveMultiplier; // 将移动方向转换为角色本地空间(如果需要跟随相机方向,可替换为Camera.main.transform.TransformDirection(moveDir)) moveDir = transform.TransformDirection(moveDir); // 保留Y轴速度,不影响跳跃等逻辑 _playerRb.velocity = new Vector3(moveDir.x, _playerRb.velocity.y, moveDir.z); }
2. 旋转控制优化
分别处理鼠标和手柄的旋转逻辑,适配两种输入的特性:
- 鼠标:直接用输入增量乘以旋转速度,实现流畅的跟随旋转
- 手柄:用摇杆X轴值作为目标角速度,做平滑过渡,避免突然转向
[SerializeField] private float _mouseRotationSpeed = 12f; [SerializeField] private float _gamepadRotationSpeed = 6f; [SerializeField] private float _rotationSmoothTime = 0.15f; private Vector2 _rotationInput; private float _currentRotationVelocity; public void OnRotation(InputAction.CallbackContext context) { _rotationInput = context.ReadValue<Vector2>(); } private void HandleRotation() { if (_currentInputDevice is Keyboard) { // 鼠标旋转:直接累加每帧增量 float rotationY = _rotationInput.x * _mouseRotationSpeed * Time.fixedDeltaTime; _playerRb.MoveRotation(_playerRb.rotation * Quaternion.Euler(0, rotationY, 0)); } else if (_currentInputDevice is Gamepad) { // 手柄旋转:平滑趋近目标角速度 float targetRotationDelta = _rotationInput.x * _gamepadRotationSpeed * Time.fixedDeltaTime; float targetRotationY = transform.eulerAngles.y + targetRotationDelta; float smoothRotationY = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetRotationY, ref _currentRotationVelocity, _rotationSmoothTime); _playerRb.MoveRotation(Quaternion.Euler(0, smoothRotationY, 0)); } } private void OnDestroy() { InputSystem.onDeviceChange -= OnDeviceChange; } }
3. 额外优化建议
- 在Input Action配置中,确保鼠标的
Look动作设置为Delta类型(默认即为该类型),保证获取的是每帧移动增量 - 给手柄摇杆添加死区配置(在Input Action的绑定属性中设置Deadzone),避免微小输入导致的误操作
- 可给键鼠移动添加加速度和减速逻辑,进一步提升手感
内容的提问来源于stack exchange,提问作者Nikolay Stuff
相关产品推荐
相关产品推荐

