MoveTowards无法到达点击点,求代码排查及Update/FixedUpdate选择建议
问题排查与解答
代码问题分析与修复
你的代码出现瞬移+无法到达目标的核心原因是:Vector3.MoveTowards只在鼠标点击的那一帧(Input.GetMouseButtonDown(0)触发瞬间)执行了一次,而非每帧持续执行移动逻辑,导致物体只动了一小段就停住,看起来像瞬移,自然也到不了目标点。
修复后的代码如下:
using UnityEngine; namespace Assets.Scripts { public class MoveToTarget : MonoBehaviour { public GameObject player; // 存储目标位置,供每帧移动逻辑读取 private Vector3 _targetPos; // 标记是否需要执行移动 private bool _isMoving = false; // 可在Inspector面板调整的移动速度 public float moveSpeed = 5f; private void Awake() { player = GameObject.Find("player"); // 初始化目标位置为玩家当前位置 _targetPos = player.transform.position; } private void Update() { // 仅在鼠标点击时更新目标位置 if (Input.GetMouseButtonDown(0)) { // 转换屏幕坐标到世界坐标,Z轴取相机与玩家的距离保证坐标正确 Vector3 clickPoint = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, Camera.main.transform.position.z - player.transform.position.z)); // 固定Y轴,仅做水平移动 _targetPos = new Vector3(clickPoint.x, player.transform.position.y, 0); _isMoving = true; } // 每帧执行移动逻辑,直到到达目标点 if (_isMoving) { player.transform.position = Vector3.MoveTowards(player.transform.position, _targetPos, moveSpeed * Time.deltaTime); // 用微小距离阈值判断是否到达目标(避免浮点数精度问题) if (Vector3.Distance(player.transform.position, _targetPos) < 0.01f) { player.transform.position = _targetPos; _isMoving = false; // 此处可添加停止行走动画的逻辑 } else { // 此处可添加播放行走动画的逻辑 } } } } }
关键修复点:
- 新增
_targetPos和_isMoving变量,让移动逻辑能脱离点击事件,在每帧持续执行 - 将移动逻辑从点击分支中独立出来,确保每帧都处理位置更新
- 增加到达目标点的判断逻辑,避免因浮点数精度导致的位置偏差
- 把移动速度设为可配置的公共变量,方便调试调整
Update 与 FixedUpdate 选择说明
- 鼠标/键盘输入必须放在
Update()中处理:FixedUpdate()是固定时间间隔执行(默认0.02秒一次),若帧率高于固定步长,会出现多次FixedUpdate对应一次Update,导致输入事件丢失;若帧率低于固定步长,又会出现输入响应延迟,只有Update能稳定捕获输入事件。 - 移动逻辑的选择:
- 像你现在直接修改
Transform的场景,移动逻辑放在Update()即可,和输入逻辑统一,代码更简洁。 - 若使用
Rigidbody组件(需要物理碰撞、重力等效果),则移动逻辑要放在FixedUpdate()里(物理引擎更新与FixedUpdate同步),此时可在Update里捕获输入,把目标位置或移动方向传递给FixedUpdate处理。
- 像你现在直接修改
内容的提问来源于stack exchange,提问作者md3sla
相关产品推荐
相关产品推荐

