You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

新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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 22:29:55