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

Unity召唤物移动逻辑问题:目标点重复更新与瞬移异常求助

问题解决:召唤物平滑移动到玩家周围随机点

问题根源分析

  • 原代码问题:Update函数每帧都会检查距离,一旦超过阈值就启动协程,导致多个协程同时运行,目标点被频繁重置,永远到不了终点。
  • 修改后代码问题:while循环内没有yield return null,会在一帧内执行完所有移动逻辑,直接瞬移到目标点,失去平滑效果;同时用transform.position != NewPositionToPlayer判断到达,因浮点数精度问题可能永远无法触发结束条件。

修正方案

  1. 添加移动状态标记,避免重复启动协程
  2. 在移动循环内加入yield return null,让移动分帧执行
  3. 改用距离阈值判断是否到达目标点,避免浮点数精度陷阱

完整修正代码

// 新增移动状态标记,防止重复启动协程
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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 20:39:07