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

Unity 2D中如何让GameObject平滑移动到随机X坐标位置?

Unity 2D 平滑移动GameObject到随机X位置的解决方案

你当前代码的核心问题是直接给position赋值导致瞬间移动,且用!=比较浮点数存在精度误差,循环内也没有帧等待逻辑,导致平滑效果完全无法实现。以下是针对性的修正方案:

核心思路

用Unity内置的Vector3.MoveTowards或Vector3.Lerp方法,这两个方法会自动处理目标在当前位置左侧/右侧的情况,无需手动判断方向;同时通过帧等待和距离阈值判断,实现逐帧平滑移动直到到达目标位置。

方案1:匀速平滑移动(推荐)

适合需要稳定移动速度的场景,用Vector3.MoveTowards实现匀速移动:

// 在类中定义可调整的移动速度(不是枚举器内部),可在Inspector面板直接修改
public float moveSpeed = 8f;

public IEnumerator fistthrust()
{
    float leftTargetX = Random.Range(-8, 8);
    float rightTargetX = Random.Range(-8, 8);
    
    // 定义极小阈值,避免浮点数精度问题导致循环无法结束
    float minDistance = 0.01f;
    
    // 循环直到两个拳头都到达目标位置
    while (Mathf.Abs(fist.transform.position.x - leftTargetX) > minDistance || 
           Mathf.Abs(rightfist.transform.position.x - rightTargetX) > minDistance)
    {
        // 构建左拳的目标位置(保留原Y、Z坐标)
        Vector3 leftTargetPos = new Vector3(leftTargetX, fist.transform.position.y, fist.transform.position.z);
        // 匀速移动左拳,Time.deltaTime保证速度不受帧率影响
        fist.transform.position = Vector3.MoveTowards(fist.transform.position, leftTargetPos, moveSpeed * Time.deltaTime);
        
        // 同理处理右拳
        Vector3 rightTargetPos = new Vector3(rightTargetX, rightfist.transform.position.y, rightfist.transform.position.z);
        rightfist.transform.position = Vector3.MoveTowards(rightfist.transform.position, rightTargetPos, moveSpeed * Time.deltaTime);
        
        // 等待下一帧,让移动效果逐帧显示
        yield return null;
    }
    
    // 移动完成后执行后续逻辑
    fistscr.down();
    yield return new WaitForSeconds(0.5f);
    rfistscr.down();
    fistscr.up();
    yield return new WaitForSeconds(0.5f);
    rfistscr.up();
    fistscr.rest();
    yield return new WaitForSeconds(0.5f);
    rfistscr.rest();
}

方案2:缓动平滑移动

适合需要先快后慢自然动画感的场景,用Vector3.Lerp实现缓动效果:

// 缓动速度,数值越大,趋近目标的速度越快
public float lerpSpeed = 5f;

public IEnumerator fistthrust()
{
    float leftTargetX = Random.Range(-8, 8);
    float rightTargetX = Random.Range(-8, 8);
    float minDistance = 0.01f;
    
    while (Mathf.Abs(fist.transform.position.x - leftTargetX) > minDistance || 
           Mathf.Abs(rightfist.transform.position.x - rightTargetX) > minDistance)
    {
        Vector3 leftTargetPos = new Vector3(leftTargetX, fist.transform.position.y, fist.transform.position.z);
        // Lerp实现缓动,逐帧趋近目标位置
        fist.transform.position = Vector3.Lerp(fist.transform.position, leftTargetPos, lerpSpeed * Time.deltaTime);
        
        Vector3 rightTargetPos = new Vector3(rightTargetX, rightfist.transform.position.y, rightfist.transform.position.z);
        rightfist.transform.position = Vector3.Lerp(rightfist.transform.position, rightTargetPos, lerpSpeed * Time.deltaTime);
        
        yield return null;
    }
    
    // 后续逻辑与方案1一致
    fistscr.down();
    yield return new WaitForSeconds(0.5f);
    rfistscr.down();
    fistscr.up();
    yield return new WaitForSeconds(0.5f);
    rfistscr.up();
    fistscr.rest();
    yield return new WaitForSeconds(0.5f);
    rfistscr.rest();
}

关键改动说明

  1. 替换直接赋值:用MoveTowards/Lerp替代直接设置position,自动处理目标方向,无需手动判断正负。
  2. 精度问题处理:用Mathf.Abs(当前X - 目标X) > 阈值替代!=,避免浮点数精度误差导致循环卡死或提前结束。
  3. 帧等待逻辑:yield return null让代码每帧执行一次,保证移动效果平滑可见。
  4. 帧率无关速度:moveSpeed * Time.deltaTime确保移动速度在不同帧率的设备上保持一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 09:02:56