- Home /
Move Transform to Target in X seconds
public Transform a;
public Transform target;
public float x = 30f; //amount of seconds for A to reach Target
I have a Transform A and a Transform target. My goal is to make A reach Target in x seconds. I have tried both Vector3.Lerp and Vector3.MoveTowards but can not figure out the problem.
What language? Would you prefer to do it in Update or in a coroutine?
C#. I prefer Update but I would use a coroutine if I need to.
Answer by whydoidoit · Aug 04, 2012 at 11:05 PM
Ok so Lerp will move you there in a guaranteed amount of time, but you need to record the starting position - which is trickier in Update.
float t;
Vector3 startPosition;
Vector3 target;
float timeToReachTarget;
void Start()
{
startPosition = target = transform.position;
}
void Update()
{
t += Time.deltaTime/timeToReachTarget;
transform.position = Vector3.Lerp(startPosition, target, t);
}
public void SetDestination(Vector3 destination, float time)
{
t = 0;
startPosition = transform.position;
timeToReachTarget = time;
target = destination;
}
Thanks a lot. After lots of hacking at my code I finally got it working correctly.
It's easier in a coroutine because you can keep it all nicely in one place.
public IEnumerator $$anonymous$$oveToPosition(Transform transform, Vector3 position, float timeTo$$anonymous$$ove)
{
var currentPos = transform.position;
var t = 0f;
while(t < 1)
{
t += Time.deltaTime / timeTo$$anonymous$$ove;
transform.position = Vector3.Lerp(currentPos, position, t);
yield return null;
}
}
startPosition = target = transform.position;
should just be:
target = transform.position
void Start() { startPosition = transform.position; }
Where/when do you call SetDestination though...?
Answer by Lakeffect · Feb 25, 2016 at 08:27 AM
Move any object to any place at any speed (units/seconds) or in any time -- all done without using Update:
StartCoroutine (MoveOverSeconds (gameObject, new Vector3 (0.0f, 10f, 0f), 5f));
public IEnumerator MoveOverSpeed (GameObject objectToMove, Vector3 end, float speed){
// speed should be 1 unit per second
while (objectToMove.transform.position != end)
{
objectToMove.transform.position = Vector3.MoveTowards(objectToMove.transform.position, end, speed * Time.deltaTime);
yield return new WaitForEndOfFrame ();
}
}
public IEnumerator MoveOverSeconds (GameObject objectToMove, Vector3 end, float seconds)
{
float elapsedTime = 0;
Vector3 startingPos = objectToMove.transform.position;
while (elapsedTime < seconds)
{
objectToMove.transform.position = Vector3.Lerp(startingPos, end, (elapsedTime / seconds));
elapsedTime += Time.deltaTime;
yield return new WaitForEndOfFrame();
}
objectToMove.transform.position = end;
}
This code is wrong. Should be objectTo$$anonymous$$ove. transform. position
.
Where? All instances of objectTo$$anonymous$$ove are followed by .transform.position in the code above -- I think...
transform.position = end;
-> objectTo$$anonymous$$ove.transform.position = end;
transform.position = Vector3.Lerp(startingPos, end, (elapsedTime / seconds));
-> objectTo$$anonymous$$ove.transform.position = Vector3.Lerp(startingPos, end, (elapsedTime / seconds));
Thanks! You're absolutely right! Sorry about the confusion.
What is the purpose of objectTo$$anonymous$$ove.transform.position = end;
- is this not handled in the while()
?
i guess with the Lerp function you are never going to reach the target position, that is how the Lerp function works. That is why when it comes out of loop the position is set to exact target position.
Lerp would work perfectly fine as long as the "t" value reaches 1 or surpasses it. However that's not the case in the original code. Since he first does the lerp and then increments his timer value he's always lagging one step behind. Since the while loop will break as soon as the timer is equal or greater than the target the last executed iteration has to result in a t value smaller than 1.
However a better solution would be to just swap the two lines and doing
elapsedTime += Time.deltaTime;
objectTo$$anonymous$$ove.transform.position = Vector3.Lerp(startingPos, end, (elapsedTime / seconds));
That way elapsedTime will actually reach (and most the time overshoot) the target "seconds" and therefore the last executed Lerp step would have a t value of at least 1 or slightly greater. Since Lerp internally clamps the t value between 0 and 1 you get a perfect 1 so you will get the target position when doing it this way.
Also you really shouldn't use WaitForEndOfFrame. It allocates memory for nothing and also carries out this calculation way after the current frame has rendered. So its effect would be seen the next frame. Just use "yield return null;" whenever you want to wait for the next frame. No garbage is allocated and it will be executed during the normal "logic" / tick time of the frame before the rendering is started.
ps: I should note that the way Unity implements Lerp for Vector3 it's not guaranteed to get the target value back with 100% accuracy. This is because they implemented it the "delta" way. The two different implementations have different advantages / disadvantages. While using the delta method does not necessarily reproduce the exact target value, the path it follows is more numerical stable a line between the two points. When using the (1-t)*a + t*b
approach we get the target (`b`) to 100% when t is 1. However the path between a and b, while still being linear, could jitter a little bit more along the line. The delta / direction approach is slightly cheaper to calculate (6 additions +3 multiply vs 6 multiply + 3 additions + 1 subtraction when you cache "1-t")
Answer by JaPete · Dec 27, 2018 at 05:05 AM
Using --- public IEnumerator MoveToPosition(Transform transform, Vector3 position, float timeToMove) { var currentPos = transform.position; var t = 0f; while(t < 1) { t += Time.deltaTime / timeToMove; transform.position = Vector3.Lerp(currentPos, position, t); yield return null; } }
This code does not work as described above by "whydoidoit"
The code makes an object Move in 4-5 seconds, when the INPUT is 1.
BROKEN FORMULA
Your answer
Follow this Question
Related Questions
Mathf.Lerp Question 2 Answers
Vector3.Lerp stick halfway 2 Answers
Vector3.Lerp completing before t = 1? 2 Answers
Creating Projectile - MoveTo/Lerp 0 Answers
Smooth swapping my game object 0 Answers