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

Unity角色移动Bug:碰撞障碍物后侧移触发突然前冲

问题分析与解决方案

问题根源

你维护的movementVelocity变量和CharacterController的实际移动状态脱节了。当角色撞到箱子时,CharacterController的实际速度(characterController.velocity)会被碰撞约束限制,但你自己的movementVelocity还在持续向目标速度(向前)逼近。等你侧移脱离箱子后,这个被“憋住”的速度会瞬间生效,导致突然冲刺。

修复方案

每次更新移动逻辑前,先将movementVelocity同步为CharacterController的实际水平速度,确保我们的速度变量和角色真实移动状态一致。

修改后的PlayerMovement类代码:

public class PlayerMovement : MonoBehaviour
{
    [SerializeField] private CharacterController characterController;
    [SerializeField] private TextMeshProUGUI speedText;
    private Vector3 movementDirection;
    private Vector3 movementVelocity;

    [SerializeField] private float accelerationSpeed = 5f;
    [SerializeField] private float decelerationSpeed = 5f;
    [SerializeField] private float movementSpeed = 20f;

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

    public void Move(Vector2 direction)
    {
        movementDirection = new Vector3(direction.x, 0f, direction.y);
    }

    public void Stop()
    {
        movementDirection = Vector3.zero;
    }

    private void Update()
    {
        // 同步movementVelocity为CharacterController的实际水平速度,排除Y轴重力影响
        movementVelocity = new Vector3(characterController.velocity.x, 0f, characterController.velocity.z);

        if (movementDirection.magnitude > 0)
        {
            Vector3 desiredVelocity = movementDirection.normalized * movementSpeed;
            movementVelocity = Vector3.MoveTowards(movementVelocity, desiredVelocity, accelerationSpeed * Time.deltaTime);
        }
        else
        {
            movementVelocity = Vector3.MoveTowards(movementVelocity, Vector3.zero, decelerationSpeed * Time.deltaTime);
        }

        Vector3 movement = transform.TransformDirection(movementVelocity) * Time.deltaTime;
        characterController.Move(movement);

        speedText.text = characterController.velocity.magnitude.ToString("0.##");
    }
}

关键修改说明

  • 在Update开头添加了movementVelocity与characterController.velocity的同步逻辑,只保留X/Z轴的水平速度(忽略Y轴的重力或跳跃速度)
  • 后续的加速/减速计算都基于同步后的真实速度,避免了“虚拟速度”累积的问题
  • 这样当角色被障碍物阻挡时,movementVelocity会被同步为实际的低速(或0),不会再累积未生效的向前速度

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 00:22:44