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

Unity Character Controller与PlayerCam相机旋转锁定问题求助

问题修正与机制讲解

核心错误分析

  1. PlayerCam脚本的旋转错误:你在设置相机localRotation时误用了transform.position.y(这是物体的Y轴位置,不是旋转值),导致相机Y轴旋转逻辑混乱,固定朝向Z轴。
  2. PlayerMovement的移动空间错误:直接使用世界空间的Horizontal/Vertical输入,没有关联相机/角色的朝向,所以移动方向始终和视角脱节。另外_direction变量从未赋值,角色旋转代码完全无效。

修正后的代码

修正版PlayerCam

public class PlayerCam : MonoBehaviour
{
    [Range(0, 1000)] public int Sens = 200; // 给默认值方便调试

    float xRotation;

    void Start()
    {
        Cursor.lockState = CursorLockMode.Locked;
        Cursor.visible = false;
    }

    void Update()
    {
        float mouseX = Input.GetAxis("Mouse X") * Sens * Time.deltaTime;
        float mouseY = Input.GetAxis("Mouse Y") * Sens * Time.deltaTime;

        // 处理上下视角(仅相机自身X轴旋转)
        xRotation -= mouseY;
        xRotation = Mathf.Clamp(xRotation, -90f, 90f);
        transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f);

        // 处理左右转向(控制父物体/角色的Y轴旋转)
        transform.parent.Rotate(Vector3.up * mouseX);
    }
}

修正版PlayerMovement

public class PlayerMovement : MonoBehaviour
{
    public float moveSpeed = 5f;
    public float jumpForce = 5f;

    private CharacterController characterController;
    private float verticalVelocity; // 手动维护Y轴速度,处理重力与跳跃

    void Start() 
    {
        characterController = GetComponent<CharacterController>();
    }

    void Update()
    {
        // 获取键盘输入
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");

        // 基于角色当前朝向(即相机水平朝向)生成移动方向
        Vector3 moveDir = transform.forward * vertical + transform.right * horizontal;
        // 归一化避免斜向移动速度过快
        if (moveDir.magnitude > 1f) moveDir.Normalize();

        // 处理重力与跳跃逻辑
        if (characterController.isGrounded)
        {
            verticalVelocity = -0.5f; // 轻微向下压,避免浮空
            if (Input.GetButtonDown("Jump"))
            {
                verticalVelocity = jumpForce;
            }
        }
        else
        {
            verticalVelocity += Physics.gravity.y * Time.deltaTime;
        }

        // 组合最终移动向量并执行移动
        Vector3 finalMovement = moveDir * moveSpeed + Vector3.up * verticalVelocity;
        characterController.Move(finalMovement * Time.deltaTime);
    }
}

关键逻辑说明

  • 相机与角色的分工:相机仅负责上下抬头(自身X轴旋转),角色(相机父物体)负责左右转向(Y轴旋转),确保视角与角色朝向完全绑定。
  • 移动空间转换:用transform.forward和transform.right获取角色当前的前后/左右方向,将键盘输入转换为角色本地空间的移动向量,实现"看向哪走哪"的效果。
  • 重力补充:CharacterController不会自动处理重力,需要手动维护Y轴速度,否则角色会一直浮空。

学习建议与练习示例

学习方向

  • 吃透Unity的空间转换:明确世界空间、本地空间的区别,掌握Transform.TransformDirection()等转换方法的用法。
  • 理解CharacterController的工作机制:区分它与Rigidbody的适用场景,熟练手动处理重力、碰撞的逻辑。
  • 掌握鼠标输入与旋转:了解四元数(Quaternion)的基本用法,避免欧拉角的万向锁问题。

练习示例

  • 视角切换功能:添加按键切换光标锁定/解锁,实现视角自由控制与UI操作的切换。
  • 冲刺功能:按住Shift时提升移动速度,松开后恢复原速。
  • 视角平滑插值:给相机旋转添加平滑过渡效果,避免视角抖动(使用Mathf.Lerp或Quaternion.Lerp)。
  • 碰撞限制优化:当角色碰到墙壁时,限制对应方向的移动,避免穿模。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 02:30:57