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

Unity如何自定义物体移动起始位置并保证移动时位置正确更新

问题根源
  • 原代码在Start()方法中就固定记录了游戏启动瞬间的物体位置作为移动起点,若你是游戏启动后才触发移动(比如运行后手动勾选go参数、其他逻辑延迟触发移动),此时如果物体位置已经发生变化,移动时就会跳回游戏启动时的位置;即使你运行前就勾选了go,出现位置重置也大概率是编辑模式下测试时originPosition被异常序列化导致。
  • 注释掉originPosition赋值语句后,该私有变量默认值为Vector3.zero,因此物体会从世界坐标原点开始插值,位置自然不符合预期。
  • 将赋值语句移到Update()中会导致每帧都用当前位置覆盖移动起点,Lerp插值的起始点不断变化,移动逻辑完全失效。
修复方案

将移动初始化逻辑(记录起始位置、重置计时器、重置状态)调整到移动指令真正触发的时刻,也就是go参数从false切换为true的瞬间,修改后代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MoveToTarget : MonoBehaviour
{
    public enum TransitionState
    {
        None,
        MovingTowards,
        Transferring
    }

    public Transform destinationTransform;
    public Transform navi;
    public Transform player;
    public bool isChild = false;
    public AnimationCurve curve = AnimationCurve.EaseInOut(0.0f, 0.0f, 1.0f, 1.0f);
    public float duration = 10.0f;
    public bool go = false;

    private float t;
    private Transform originTransform;
    private float timer;
    private TransitionState state = TransitionState.MovingTowards;
    private Vector3 originPosition;
    // 新增标记:记录移动是否已经初始化
    private bool _moveStarted = false;

    void Start()
    {
        curve.postWrapMode = WrapMode.Once;
    }

    void Update()
    {
        // 检测到移动指令触发,且未初始化过移动时执行初始化
        if (go && !_moveStarted)
        {
            originPosition = transform.position;
            t = 0f;
            state = TransitionState.MovingTowards;
            _moveStarted = true;
        }
        // 检测到移动指令取消,重置初始化标记,支持下次重新触发移动
        else if (!go && _moveStarted)
        {
            _moveStarted = false;
        }

        if (go)
        {
            switch (state)
            {
                case TransitionState.MovingTowards:
                    var v = destinationTransform.position - transform.position;
                    if (v.magnitude < 0.001f)
                    {
                        state = TransitionState.Transferring;
                        originTransform = destinationTransform;
                        timer = 0;
                        return;
                    }

                    t += Time.deltaTime;
                    float s = t / duration;

                    transform.position = Vector3.Lerp(originPosition,
                        destinationTransform.position, curve.Evaluate(s));
                    break;

                case TransitionState.Transferring:
                    timer += Time.deltaTime;
                    this.transform.position = Vector3.Lerp(originTransform.position, destinationTransform.position, timer);

                    if (timer >= 1.0f)
                    {
                        this.transform.parent = destinationTransform;
                        transform.localPosition = new Vector3(0, 0, 0);
                        isChild = true;

                        state = TransitionState.None;
                        this.enabled = false;
                        return;
                    }
                    break;

                default:
                    this.enabled = false;
                    return;
            }
        }
    }
}
修改说明
  • 现在你可以在编辑器运行游戏前,任意拖拽调整物体的位置,只要运行后触发go = true(运行前就勾选go也可以),物体就会从你设置的位置开始向目标点移动。
  • 额外支持中途停止再重新移动的需求:如果移动过程中取消go的勾选,下次再勾选时物体会从当前所在位置重新开始向目标点移动。

内容的提问来源于stack exchange,提问作者Daniel Lip

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 00:45:00