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

如何让Unity角色旋转与相机rotation一致,按下W沿相机朝向移动

问题根因

  • 你当前的移动逻辑用的是世界坐标系的固定方向(Vector3.forward/Vector3.left等),和相机/角色的朝向完全无关,所以不管怎么旋转相机,移动方向都是固定的
  • 两个脚本同时修改target.rotation会出现执行顺序冲突,原相机脚本也没有处理Y轴旋转限制,容易出现视角翻转问题
  • 刚体速度修改逻辑写在Update里会受帧率波动影响,不符合Unity物理系统的规范
  • 没有对移动方向的Y轴做过滤,相机抬头低头时会导致角色往天空/地面方向偏移

修复步骤

  1. 删掉相机脚本里的target.rotation = Cam.rotation逻辑,只保留角色移动脚本里的朝向同步,避免执行顺序冲突
  2. 移动方向改用相机的朝向向量,过滤Y轴分量保证角色只在水平面上移动
  3. 把刚体相关的操作移到FixedUpdate中执行
  4. 初始化移动速度基础值,新增方向归一化逻辑避免斜向移动速度过快

修正后角色移动脚本

public Rigidbody rb;
public float moveSpeed = 5f; // 初始化基础移动速度
public Transform Cam;
public Transform target;

private Vector3 moveDir;

// 物理操作统一放在FixedUpdate执行
private void FixedUpdate()
{
    // 仅同步水平方向朝向,避免相机抬头低头导致角色歪倒
    target.rotation = Quaternion.Euler(0, Cam.rotation.eulerAngles.y, 0);
    
    // 把本地坐标系方向转为世界坐标系方向后应用速度
    rb.velocity = target.TransformDirection(moveDir) * moveSpeed;
}

void Update()
{
    moveDir = Vector3.zero;
    // Update仅做输入检测,不直接操作刚体
    if (Input.GetKey(KeyCode.W))
    {
        moveDir += Vector3.forward;
    }
    if (Input.GetKey(KeyCode.S))
    {
        moveDir += Vector3.back;
    }
    if (Input.GetKeyDown(KeyCode.Space))
    {
        rb.velocity = new Vector3(rb.velocity.x, moveSpeed, rb.velocity.z);
    }
    if (Input.GetKey(KeyCode.A))
    {
        moveDir += Vector3.left;
    }
    if (Input.GetKey(KeyCode.D))
    {
        moveDir += Vector3.right;
    }
    // 速度切换逻辑
    if(Input.GetKey(KeyCode.LeftShift))
    {
        moveSpeed = 8f;
    }
    else if(Input.GetKey(KeyCode.LeftControl))
    {
        moveSpeed = 3f;
    }
    else
    {
        moveSpeed = 5f; // 松开按键后恢复默认速度
    }
    // 方向向量归一化,避免斜向移动速度过快
    if (moveDir.magnitude > 1)
    {
        moveDir.Normalize();
    }
}

修正后相机跟随脚本

public float rotateSpeed;
private float moveX;
public Transform target;
public Vector3 offset;
private float moveY;
// 限制上下视角范围,避免视角翻转
public float minViewAngle = -60f;
public float maxViewAngle = 60f;

void Update()
{
    transform.position = target.position + offset;
    moveX = Input.GetAxis("Mouse X");
    moveY = Input.GetAxis("Mouse Y");
    // 水平旋转绕世界Y轴,垂直旋转绕自身X轴
    transform.Rotate(Vector3.up, moveX * rotateSpeed * Time.deltaTime, Space.World);
    transform.Rotate(Vector3.right, -moveY * rotateSpeed * Time.deltaTime, Space.Self);
    // 对垂直旋转角度做钳制
    Vector3 currentEuler = transform.localEulerAngles;
    currentEuler.x = ClampAngle(currentEuler.x, minViewAngle, maxViewAngle);
    currentEuler.z = 0;
    transform.localEulerAngles = currentEuler;
}

// 角度钳制辅助方法,处理0-360度的跳转问题
private float ClampAngle(float angle, float min, float max)
{
    if (angle < 0f) angle += 360f;
    if (angle > 180f) angle -= 360f;
    return Mathf.Clamp(angle, min, max);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 23:36:04