Unity协程重启问题:往返移动协程返回原点后无法执行?
问题分析与修复
核心问题点
- 协程实例无法重复执行:你在
Start()里创建了一个IEnumerator实例并存在coroutine变量中,但迭代器执行完毕后就会处于耗尽状态,无法通过StartCoroutine(coroutine)再次启动。 - 浮点数精确比较不可靠:
transform.position.y == 4用精确等于判断浮点数,由于Unity物体移动的浮点精度误差,这个条件几乎不会被触发,导致协程根本没机会重新启动。 - 协程内部逻辑缺陷:
currentPos仅在协程启动时记录一次,Vector3.Lerp的起点不会随物体位置变化,移动逻辑不符合预期;- 循环里的
currentPos.y > position.y条件多余,还会限制移动方向; - 手动调用
StopCoroutine(coroutine)完全没必要,协程执行完毕后会自动终止。
修复后的代码
public class LineManager : MonoBehaviour { public Vector3 positionToGo = new Vector3(0, -4, 0); public float timeToMove = 2f; private bool isMoving = false; // 防止协程重复启动 void Update() { // 用接近值判断代替精确等于,同时加锁避免重复启动 if (Mathf.Approximately(transform.position.y, 4f) && !isMoving) { StartCoroutine(MoveToPosition(transform, positionToGo, timeToMove)); } } public IEnumerator MoveToPosition(Transform transform, Vector3 targetPos, float duration) { isMoving = true; Vector3 startPos = transform.position; float t = 0f; // 移动到目标点 while (t < 1f) { t += Time.deltaTime / duration; transform.position = Vector3.Lerp(startPos, targetPos, t); yield return null; } transform.position = targetPos; // 确保精确到达目标点 // 可选:停留一段时间再返回 yield return new WaitForSeconds(0.5f); // 移动回原点 t = 0f; startPos = transform.position; Vector3 originPos = new Vector3(0, 4, 0); while (t < 1f) { t += Time.deltaTime / duration; transform.position = Vector3.Lerp(startPos, originPos, t); yield return null; } transform.position = originPos; isMoving = false; } }
关键修复说明
- 每次启动协程时直接调用
MoveToPosition方法创建新的迭代器实例,不再复用旧实例; - 用
Mathf.Approximately判断浮点数是否接近,彻底避免精度问题; - 增加
isMoving布尔变量,防止协程被重复触发; - 重构协程内部逻辑,先完成到目标点的移动,再执行返回原点的流程,逻辑更清晰;
- 移除不必要的
StopCoroutine调用,协程执行完毕会自动停止。
内容的提问来源于stack exchange,提问作者Jinwoo-L
相关产品推荐
相关产品推荐

