使用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
相关产品推荐
相关产品推荐

