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(); }
关键改动说明
- 替换直接赋值:用
MoveTowards/Lerp替代直接设置position,自动处理目标方向,无需手动判断正负。 - 精度问题处理:用
Mathf.Abs(当前X - 目标X) > 阈值替代!=,避免浮点数精度误差导致循环卡死或提前结束。 - 帧等待逻辑:
yield return null让代码每帧执行一次,保证移动效果平滑可见。 - 帧率无关速度:
moveSpeed * Time.deltaTime确保移动速度在不同帧率的设备上保持一致。
内容的提问来源于stack exchange,提问作者mmiv
相关产品推荐
相关产品推荐

