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

如何调整角色lerp移动时长:从0.1秒改为1秒?

解决角色移动过快(瞬移)问题:调整移动时长为1秒

嘿,我明白你遇到的问题了——原来的Lerp插值只给了0.1秒完成,角色自然会像瞬移一样消失。要改成1秒的平滑移动,核心是让插值进度均匀覆盖1秒的时间,而不是用固定的小数值来做每帧的插值。

问题根源

你之前的代码应该是直接在每帧调用Vector3.Lerp时传入了类似0.1f的参数,这种写法其实是做指数平滑(快速趋近目标),而且整个过程会在0.1秒内完成,所以看起来像瞬移。我们需要改成线性插值,严格控制总时长为1秒。

两种可行的修改方案

方案1:用协程实现(推荐,逻辑更清晰)

协程可以很方便地控制整个移动过程的生命周期,还能随时中断或暂停。下面是完整的示例代码:

using UnityEngine;
using System.Collections;

public class CharacterMovement : MonoBehaviour
{
    // 固定移动时长为1秒,也可以暴露给Inspector调整
    [SerializeField] private float moveDuration = 1f;

    // 调用这个方法来让角色移动到目标位置
    public void MoveToPosition(Vector3 targetPosition)
    {
        // 如果正在移动,先停止之前的协程,避免冲突
        StopCoroutine(nameof(SmoothMoveCoroutine));
        StartCoroutine(SmoothMoveCoroutine(targetPosition));
    }

    private IEnumerator SmoothMoveCoroutine(Vector3 targetPos)
    {
        Vector3 startPosition = transform.position;
        float timeElapsed = 0f;

        // 循环直到时间用完
        while (timeElapsed < moveDuration)
        {
            // 计算当前进度:已用时间 / 总时长,范围0(开始)到1(结束)
            float moveProgress = timeElapsed / moveDuration;
            // 用进度做线性插值,得到当前位置
            transform.position = Vector3.Lerp(startPosition, targetPos, moveProgress);
            
            // 累加当前帧的时间
            timeElapsed += Time.deltaTime;
            // 等待下一帧再继续
            yield return null;
        }

        // 最后强制把位置设为目标点,避免浮点误差导致的偏移
        transform.position = targetPos;
    }
}

方案2:在Update里实现(适合简单场景)

如果不想用协程,也可以在Update里跟踪移动状态:

using UnityEngine;

public class CharacterMovement : MonoBehaviour
{
    [SerializeField] private float moveDuration = 1f;
    
    private Vector3 _targetPosition;
    private Vector3 _startPosition;
    private float _timeElapsed;
    private bool _isMoving;

    public void MoveToPosition(Vector3 targetPosition)
    {
        _targetPosition = targetPosition;
        _startPosition = transform.position;
        _timeElapsed = 0f;
        _isMoving = true;
    }

    void Update()
    {
        if (!_isMoving) return;

        _timeElapsed += Time.deltaTime;
        // 用Clamp01确保进度不会超过1
        float moveProgress = Mathf.Clamp01(_timeElapsed / moveDuration);
        transform.position = Vector3.Lerp(_startPosition, _targetPosition, moveProgress);

        // 移动完成后关闭状态
        if (moveProgress >= 1f)
        {
            _isMoving = false;
            transform.position = _targetPosition;
        }
    }
}

关键说明

  • 两种方案都是用已用时间 / 总时长来计算0到1的进度,这样就能保证移动过程刚好花1秒完成
  • 协程方案更适合需要在移动过程中添加额外逻辑(比如播放动画、检测碰撞)的场景
  • 最后强制设置目标位置是为了避免浮点运算的微小误差,让角色精确到达目标点

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:09:25