The problem is that I'm using Lerp and if I'm making the transform to move from the originPosition to the target(destinationTransform) it's not moving from the player hand but from another position near the player.

This screenshot is the transform object in the player hand as the original position it's should be the original position :

transform is child of the player hand

Then when the transform start moving to the target he start moving not from the hand but from a position near the hand :

transform is moving to the target but not from the hand

This line is making the transform moving :

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

If I'm changing in this line from originPosition to transform.position then it will move from the hand but the duration will not be 10 seconds or the time I'm setting.

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

What I'm trying to do is to move the transform to the target stay at the target hang there X seconds and the start moving back.

and only when it's moving back top make the transform in the end to be Transferring as child of the target(the player hand) when reaching to the target that is not the player hand don't make it child only on the way back.

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

public class MoveToTarget : MonoBehaviour
    public enum TransitionState

    public Transform destinationTransform;
    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 SphereCollider col;
    private bool enableCollider = true;

    void Start()
        t = 0.0f;

        curve.postWrapMode = WrapMode.Once;
        originPosition = transform.position;
        col = GetComponent<SphereCollider>();

    void Update()
        if (go)
            if (col != null && enableCollider)
                //col.enabled = false;
                //transform.GetComponent<Rigidbody>().isKinematic = true;

                transform.GetComponent<InteractableItem>().enabledInteraction = false;

                enableCollider = false;

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

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

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

                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;

                        go = false;

                        state = TransitionState.None;
                        this.enabled = false;

                    this.enabled = false;

Okay. Depending on what you're doing with this, a coroutine might be more appropriate. It allows you to "fire and forget", with the added bonus that local variables are kept alive as long as the coroutine is, so you don't need long-lived state cluttering your classes up.

I think you're overcomplicating things, unless there's more logic not shown that explains the structure you've adopted.

How about something like this:

    IEnumerator GoAndReturn(Vector3 target, float duration = 10) {
        var parent = this.transform.parent;
        this.transform.parent = null;

        var originPosition = this.transform.position;

        var startTime = Time.timeAsDouble;

        var t = 0f;
        while (t <= 1) {
            // t varies from 0 to 1 over duration
            t = (float)((Time.timeAsDouble - startTime) / duration);
            // Assuming a curve that returns from 0 to 1 as s varies 0->1
            if (t < 0.5) {
                // Outward journey
                transform.position = Vector3.Lerp(originPosition, target, curve.Evaluate(t * 2));
            } else {
                //return journey
                transform.position = Vector3.Lerp(parent.transform.position, target, curve.Evaluate((1 - t) * 2));
            yield return null;
        this.transform.parent = parent;
        this.transform.localPosition = Vector3.zero;

Then you can invoke it with:



    StartCoroutine(GoAndReturn(destinationTransform, duration: 5));
  • \$\begingroup\$ timeAsDouble is not exist as Time property. \$\endgroup\$ Jan 6 at 0:56
  • \$\begingroup\$ It's moving to the target smooth but on the return the object just appears at the player hand at once it's not moving back from the target to the player hand. \$\endgroup\$ Jan 6 at 0:59
  • \$\begingroup\$ @chkfmysfms It does ... imgur.com/a/ouGFizs. To avoid confusion, I'm referring to UnityEngine.Time.timeAsDouble ... docs.unity3d.com/2020.2/Documentation/ScriptReference/… \$\endgroup\$
    – Basic
    Jan 6 at 1:00
  • \$\begingroup\$ @chkfmysfms I fixed a bug. Make sure the second lerp starts parent.transform.position \$\endgroup\$
    – Basic
    Jan 6 at 1:01
  • \$\begingroup\$ for the first problem with the timeAsDouble it's existing in unity 2020.2 version but my project is on 2019 version. \$\endgroup\$ Jan 6 at 1:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .