# How to make the object to move to the target smooth ease in out from the player hand and back?

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 :

Then when the transform start moving to the target he start moving not from the hand but from a position near 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
{
None,
MovingTowards,
Transferring
}

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;

Destroy(col);
Destroy(transform.GetComponent<Rigidbody>());
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;
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;

go = false;

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

default:
this.enabled = false;
return;
}
}
}
}


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.

    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));


or

    StartCoroutine(GoAndReturn(destinationTransform, duration: 5));

• timeAsDouble is not exist as Time property. Jan 6 at 0:56
• 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. Jan 6 at 0:59
• @chkfmysfms It does ... imgur.com/a/ouGFizs. To avoid confusion, I'm referring to UnityEngine.Time.timeAsDouble ... docs.unity3d.com/2020.2/Documentation/ScriptReference/… Jan 6 at 1:00
• @chkfmysfms I fixed a bug. Make sure the second lerp starts parent.transform.position Jan 6 at 1:01
• for the first problem with the timeAsDouble it's existing in unity 2020.2 version but my project is on 2019 version. Jan 6 at 1:05