Unity召唤物移动逻辑问题:目标点重复更新与瞬移异常求助
问题解决:召唤物平滑移动到玩家周围随机点
问题根源分析
- 原代码问题:Update函数每帧都会检查距离,一旦超过阈值就启动协程,导致多个协程同时运行,目标点被频繁重置,永远到不了终点。
- 修改后代码问题:while循环内没有
yield return null,会在一帧内执行完所有移动逻辑,直接瞬移到目标点,失去平滑效果;同时用transform.position != NewPositionToPlayer判断到达,因浮点数精度问题可能永远无法触发结束条件。
修正方案
- 添加移动状态标记,避免重复启动协程
- 在移动循环内加入
yield return null,让移动分帧执行 - 改用距离阈值判断是否到达目标点,避免浮点数精度陷阱
完整修正代码
// 新增移动状态标记,防止重复启动协程 private bool isMoving = false; public float MaxDistanceToPlayer = 10f; public float WalkSpeed = 2f; public Transform Player; void Update() { float distanceToPlayer = Vector3.Distance(Player.position, transform.position); // 只有当距离超过阈值且未在移动时,才启动移动协程 if (distanceToPlayer >= MaxDistanceToPlayer && !isMoving) { StartCoroutine(MovingToPlayer()); } } IEnumerator MovingToPlayer() { isMoving = true; // 生成玩家周围的随机目标点 Vector3 targetPosition = Player.position + new Vector3(Random.Range(-2.0f, 2.0f), 0f, Random.Range(-2.0f, 2.0f)); Debug.DrawLine(transform.position, targetPosition, Color.red, 0.1f); // 改用距离小于阈值判断到达,避免浮点数精度问题 while (Vector3.Distance(transform.position, targetPosition) > 0.01f) { float step = WalkSpeed * Time.deltaTime; transform.position = Vector3.MoveTowards(transform.position, targetPosition, step); // 每一帧移动后暂停,实现平滑效果 yield return null; } // 确保最终位置精确到目标点(可选) transform.position = targetPosition; isMoving = false; }
关键改动说明
isMoving标记:在协程启动时设为true,结束时设为false,避免Update重复触发协程,保证每个目标点只执行一次移动逻辑。- 分帧移动:
yield return null让协程每帧执行一次移动代码,配合Time.deltaTime保证移动速度不受帧率影响。 - 精度处理:用
Vector3.Distance(...) > 0.01f替代直接比较位置,解决浮点数运算导致的无法到达问题。
内容的提问来源于stack exchange,提问作者Alexey
相关产品推荐
相关产品推荐

