Vector3 始终不相等:相机移动到位判定失效问题
问题分析与解决方案
核心问题1:浮点精度与Lerp特性导致判定失效
你使用的Vector3.Lerp(transform.position, destination, speed)是指数式趋近的插值逻辑:每帧仅移动当前位置到目标点的speed比例距离。当speed很小(比如0.03f)时,每次移动的步长会持续缩小,理论上永远无法精确等于目标点——Debug日志显示的是四舍五入后的数值,实际内存中两个Vector3的分量仍存在微小差异,因此Equals或==判定始终不成立。
而speed较大时(比如0.1f),某次移动会直接跨过Unity内置近似相等的阈值,此时==运算符能触发判定。
核心问题2:Lerp调用方式导致移动速度异常
你当前的Lerp没有结合时间增量(Time.deltaTime),移动速度会随帧率波动;调换Lerp和Debug.Log的顺序后,日志显示的是移动前/后的位置,再加上Lerp的指数特性,会让你误以为速度变化,本质是观察时机的问题。
修复后的代码方案
推荐使用Vector3.MoveTowards替代Lerp,它会以匀速移动到目标点,到达时直接将位置设为目标值,完美解决精度问题:
void MoveToward(Vector3 destination, float speed) { if (!started) return; // 结合Time.deltaTime保证帧率无关的匀速移动 float step = speed * Time.deltaTime; transform.position = Vector3.MoveTowards(transform.position, destination, step); // 用距离阈值判定是否到达,规避浮点精度问题 if (Vector3.Distance(transform.position, destination) < 0.001f) { // 强制将位置设为目标点,消除微小偏移 transform.position = destination; started = false; Debug.Log("Arrived!"); } }
额外说明
- 若坚持用Lerp实现匀速移动
需要基于初始位置和目标点做插值,而非每帧用当前位置:// 需额外记录初始位置startPos和移动时长duration float elapsedTime = 0f; void MoveToward(Vector3 destination, float duration) { if (!started) return; elapsedTime += Time.deltaTime; float t = Mathf.Clamp01(elapsedTime / duration); transform.position = Vector3.Lerp(startPos, destination, t); if (t >= 1f) { started = false; Debug.Log("Arrived!"); } } - 关于
Vector3 ==的近似判定
Unity的Vector3 ==确实会用近似逻辑,但误差范围极小(约1e-5),当Lerp步长小于该范围时就无法触发判定,因此用Vector3.Distance加自定义阈值更可靠。
内容的提问来源于stack exchange,提问作者Jacob Mueller
相关产品推荐
相关产品推荐

