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

使用Lerp实现角色向前跳跃移动时触发无限循环问题求助

问题分析与解决

为什么会冻结?

你代码里的while(transform.position != endPos)是直接导致Unity卡死的原因。Unity的Update方法是单帧内同步执行的,这个while循环会在按下W的瞬间占据主线程无限循环——一方面浮点型的位置值几乎不可能完全等于endPos,另一方面循环里没有任何让游戏时间推进的逻辑,直接导致程序彻底冻结。

正确的平滑移动实现方式

Lerp实现平滑移动需要把移动逻辑拆分到每一帧执行,而不是在一帧内用循环硬推。我们可以用一个状态变量标记是否正在移动,然后在Update里逐帧更新位置:

修改后的代码

private Rigidbody playerRb;
private CapsuleCollider playerColl;

private Vector3 startPos;
private Vector3 endPos;

[SerializeField] private float jumpSpeed = 1f;

private float startTime;
private float jumpLength;
// 标记是否处于移动状态
private bool isMoving = false;

private void Start()
{
    playerRb = GetComponent<Rigidbody>();
    playerColl = GetComponent<CapsuleCollider>();
}

void Update()
{
    if (Input.GetKeyDown(KeyCode.W) && !isMoving)
    {
        startTime = Time.time;
        startPos = playerRb.transform.position;
        endPos = startPos + Vector3.forward; // 向前移动1单位
        jumpLength = Vector3.Distance(startPos, endPos);
        isMoving = true;
    }

    // 逐帧处理移动逻辑
    if (isMoving)
    {
        float distCovered = (Time.time - startTime) * jumpSpeed;
        float fraction = distCovered / jumpLength;
        // 用Rigidbody的MovePosition更符合物理规则
        playerRb.MovePosition(Vector3.Lerp(startPos, endPos, fraction));

        // 当移动完成时关闭状态,避免浮点误差直接设为终点
        if (fraction >= 1f)
        {
            playerRb.MovePosition(endPos);
            isMoving = false;
        }
    }
}

关键改动说明

  • 新增isMoving布尔变量,防止在移动过程中重复触发新的移动指令
  • 按下W时只初始化移动参数,不执行循环,把移动逻辑放到Update的帧循环里
  • 使用playerRb.MovePosition代替直接修改transform.position,让物理引擎正确处理碰撞和刚体交互
  • 当fraction >=1时直接将位置设为endPos,避免浮点精度问题导致的位置偏差

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 01:52:47