Unity中Mathf.MoveTowards(z,2f,Time.deltaTime)失效问题求助
问题分析与解决
核心问题根源
你犯了一个典型的逻辑错误:每一帧都用Input.GetAxis("Vertical")直接覆盖变量z,导致Mathf.MoveTowards的平滑结果根本无法累积。Input.GetAxis返回的是-1到1之间的实时输入值,你刚用MoveTowards算出的平滑值,下一帧就被输入值冲掉了,自然无法向目标值移动。
针对各个异常点的具体解释
Mathf.MoveTowards(z, 2f, Time.deltaTime)无效
因为z每一帧都被重置为-1~1的输入值,不管你怎么MoveTowards到2,下一秒z又回到输入范围,永远碰不到2。目标设为1f时会超出到1.003
这是浮点数精度的正常现象:当当前值和目标值的差值小于步长Time.deltaTime时,Mathf.MoveTowards会直接将当前值设为目标,但浮点数的二进制存储会带来微小计算误差,加上Time.deltaTime本身是波动的(比如帧间隔不稳定),就会出现极微小的超界。乘2或修改
Time.deltaTime导致瞬时完成- 把
z乘以2只是把输入范围扩大到-2~2,但你依然是用输入值直接覆盖z,MoveTowards的结果无法保留,等于没做平滑。 - 如果把
Time.deltaTime换成固定大值,步长会远大于当前值到目标的距离,Mathf.MoveTowards会直接跳到目标,自然变成瞬时完成。
- 把
正确的实现方式
你需要拆分两个变量:一个用来接收输入的目标值,另一个用来存储平滑过渡的当前值。示例代码如下:
// 维护一个平滑过渡的当前值 float currentZ = 0f; // 接收输入的目标值(可按需调整范围) float targetZ = 0f; void Update() { // 用输入更新目标值,将原-1~1范围映射到-2~2 targetZ = Input.GetAxis("Vertical") * 2f; // 对currentZ做平滑过渡,每次Update累积结果 currentZ = Mathf.MoveTowards(currentZ, targetZ, Time.deltaTime * 5f); // 5f为平滑速度,可自行调整 // 可选:限制范围彻底避免浮点数超界 currentZ = Mathf.Clamp(currentZ, -2f, 2f); }
额外优化建议
- 若要严格限制不超界,在MoveTowards后加上
Mathf.Clamp是最直接的方法。 - 若想避免微小的精度波动,可通过
Mathf.Approximately判断当前值是否接近目标,接近时直接设为目标:if (Mathf.Approximately(currentZ, targetZ)) { currentZ = targetZ; } else { currentZ = Mathf.MoveTowards(currentZ, targetZ, Time.deltaTime * 5f); }
内容的提问来源于stack exchange,提问作者Ivan
相关产品推荐
相关产品推荐

