SagiZiv
SagiZiv

Reputation: 1040

Unity awaitForSeconds called before lerp animation ends

I have created a simple lerp animation that moves an object from one place to the other using this code:

public IEnumerator Move(Vector3 position, Transform transform, float animationTime = 1)
{
float timePassed = 0;
transform.position = Vector3.Lerp(startPos, position, timePassed /animationTime);
timePassed += Time.deltaTime;
yield return null;
}

and I call it from another script. But I want it to do something after the animation. if I create a Coroutine and use yield return WaitForSeconds(animationTime); the Coroutine ends before the animation and it causes bugs.

I have also tried to create variable that count the time passed (like in the animation) but for no avail…

What am I doing wrong ¿

EDIT: I can't change the Move function because it is used in other classes and I want to make it as generic as possible

Upvotes: 4

Views: 704

Answers (4)

Daniel Linder
Daniel Linder

Reputation: 24

You can try and use this to send back a return value after the coroutine is done:

void Move(Vector3 position, Transform transform, float animationTime = 1) {

StartCoroutine(DoMove(position, transform, (moveIsDone) => {if(moveIsDone) { ... };});


IEnumerator DoMove(Vector3 position, Transform transform, float animationTime, System.Action<bool> callback)
{

    float timer = 0f;
    while(timer < 1f)
    {
        timer += Time.deltaTime / animationTime;
        transform.position = Vector3.Lerp(startPos, position, timer);
        yield return null;
    }
    callback(true);

}

Upvotes: 0

Tanaka
Tanaka

Reputation: 97

You can use a coroutine and loop every frame, and after the loop is done you can just trigger a callback. A quick example can be:

public IEnumerator Move(Vector3 position, Transform transform, float animationTime = 1, Action callback = null)
{
    float lerp = 0;
    do
    {
        lerp += Time.deltaTime / animationTime;
        transform.position = Vector3.Lerp(startPos, position, lerp);
        yield return null; // wait for the end of frame
    } while (lerp < 1);

    if (callback != null)
        callback();
}

P.S.: I didn't test this code in editor. It may have any typo.

Upvotes: 0

kefren
kefren

Reputation: 1102

You can put this in a Coroutine:

float timePassed=0.0f;
while(timePassed<=animationTime)
{
 transform.position = Vector3.Lerp(startPos, position, timePassed /animationTime);
 timePassed += Time.deltaTime;
 yield return null;
}
//all the stuff you want to do after the animation ended

Upvotes: 0

KYL3R
KYL3R

Reputation: 4073

A coroutine that runs the "same time" as the animation? Sounds like it can easily break on different fps.

I highly recommend you to use an AnimationEvent on the last keyframe. Just create a public method and keyframe Event in your animation, then select the method. It will be called at the end.

Upvotes: 1

Related Questions