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

Unity 6新输入系统下如何用键盘Q/E键实现虚拟相机旋转?

Unity 6新输入系统相机Q/E旋转失效问题修复

问题核心原因

你的代码存在几个关键问题导致Q/E旋转失效:

  • 多余的鼠标中键判断:RotateCamera方法里仅允许按住鼠标中键时执行旋转,但Q/E是键盘输入,和鼠标操作无关
  • rotation变量未初始化:Update中调用rotation.ReadValue<Vector2>()时变量为空,未触发报错是因为代码逻辑未走到该分支
  • 旋转赋值错误:直接覆盖transform.rotation而非增量旋转,无法实现持续旋转效果
  • 输入动作回调逻辑不匹配Q/E的按键输入模式

修复步骤及代码修改

1. 初始化输入动作变量

在OnEnable方法中补充rotation变量的赋值,同时添加按键抬起的回调监听:

private void OnEnable()
{
    lastPosition = this.transform.position;
    movement = cameraActions.Camera.Movement;
    rotation = cameraActions.Camera.CamRotation; // 初始化旋转动作变量
    cameraActions.Camera.Enable();
    cameraActions.Camera.CamRotation.performed += RotateCamera;
    cameraActions.Camera.CamRotation.canceled += RotateCamera; // 监听按键抬起事件
}

2. 移除鼠标限制并修正旋转逻辑

修改RotateCamera方法,去掉鼠标中键判断,改为增量旋转模式:

private void RotateCamera(InputAction.CallbackContext inputValue)
{
    float rotateInput = inputValue.ReadValue<Vector2>().x;
    // 基于当前旋转增量更新,而非直接覆盖
    transform.Rotate(Vector3.up, rotateInput * maxRotationSpeed * Time.deltaTime);
}

3. 调整输入动作绑定(关键)

确保你的CamRotation输入动作绑定符合以下要求:

  • Q键绑定到CamRotation的X轴,设置值为**-1**
  • E键绑定到CamRotation的X轴,设置值为**+1**
  • 输入动作Type设为Value,Control Type设为Axis 2D(或Axis 1D对应X轴)

4. 清理无用代码

删除Update中未使用的Vector2 rotationValue = rotation.ReadValue<Vector2>();语句,避免空引用风险。

完整修复后的代码

using System;
using Unity.Mathematics;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Rendering;

public class CameraController : MonoBehaviour
{
    private PlayerControls cameraActions;
    private InputAction movement;
    private Transform cameraTransform;
    private InputAction rotation;

    [SerializeField]
    private float maxSpeed = 5f;
    private float currentSpeed;
    [SerializeField]
    private float acceleration = 10f;
    [SerializeField]
    private float damping = 15f;

    [SerializeField]
    private float maxRotationSpeed = 100f; // 建议调大数值,原1f旋转速度过慢

    private Vector3 targetPosition;
    private Vector3 horizontalVelocity;
    private Vector3 lastPosition;
    Vector3 startDrag;

    private void Awake()
    {
        cameraActions = new PlayerControls();
        cameraTransform = this.GetComponentInChildren<Camera>().transform;
    }

    private void OnEnable()
    {
        lastPosition = this.transform.position;
        movement = cameraActions.Camera.Movement;
        rotation = cameraActions.Camera.CamRotation;
        cameraActions.Camera.Enable();
        cameraActions.Camera.CamRotation.performed += RotateCamera;
        cameraActions.Camera.CamRotation.canceled += RotateCamera;
    }

    private void OnDisable()
    {
        cameraActions.Camera.CamRotation.performed -= RotateCamera;
        cameraActions.Camera.CamRotation.canceled -= RotateCamera;
        cameraActions.Camera.Disable();
    }

    private void Update()
    {
        GetKeyboardMovement();
        UpdateVelocity();
        UpdateBasedPosition();
    }

    private void UpdateVelocity()
    {
        horizontalVelocity = (this.transform.position - lastPosition) / Time.deltaTime;
        horizontalVelocity.y = 0;
        lastPosition = this.transform.position;
    }

    private void GetKeyboardMovement()
    {
        Vector3 inputValue = movement.ReadValue<Vector2>().x * GetCameraRight()
                        + movement.ReadValue<Vector2>().y * GetCameraForward();
        inputValue = inputValue.normalized;

        if (inputValue.sqrMagnitude > 0.1f)
            targetPosition += inputValue;
    }

    private Vector3 GetCameraRight()
    {
        Vector3 right = cameraTransform.right;
        right.y = 0;    
        return right;
    }

    private Vector3 GetCameraForward()
    {
        Vector3 forward = cameraTransform.forward;
        forward.y = 0;
        return forward;
    }

    private void UpdateBasedPosition()
    {
        if (targetPosition.sqrMagnitude > 0.1f)
        {
           currentSpeed = Mathf.Lerp(currentSpeed, maxSpeed, Time.deltaTime * acceleration);
           transform.position += targetPosition * currentSpeed * Time.deltaTime;
        }
        else
        {
            horizontalVelocity = Vector3.Lerp(horizontalVelocity, Vector3.zero, Time.deltaTime * damping);
            transform.position += horizontalVelocity * Time.deltaTime;
        }
        targetPosition = Vector3.zero;
    }

    private void RotateCamera(InputAction.CallbackContext inputValue)
    {
        float rotateInput = inputValue.ReadValue<Vector2>().x;
        transform.Rotate(Vector3.up, rotateInput * maxRotationSpeed * Time.deltaTime);
    }
}

额外提示

  • 建议将maxRotationSpeed调至100左右,原1f的旋转速度会非常缓慢
  • 确保Unity项目设置中已启用新输入系统,且PlayerControls输入动作资源已正确生成
  • 测试时可在RotateCamera方法中添加Debug.Log(rotateInput),验证Q/E键是否能输出正确的-1/1值

内容的提问来源于stack exchange,提问作者agfessel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 20:05:57