How to fine control an animation?

Good morning,

i have a GameObject animated via the Animator component.

My goal is to set with a script the last position for the animation, in other words i want to specify where the GameObject will end the animation in terms of its transform.position

I found a hacky way to do it and i wanted to share my idea and ask for a better solution:

Basically i fire an event at the end of the animation and from there i set the transform.position of the GameObject.

Unfortunately is not so straightforward.

  • If you try to set the transform.position in the function called by the event it will be overridden by the animation itself, EVEN IF YOU DISABLE the animator component.

So i went for the coroutine path : in the function called by the event i disable the animator and start a Coroutine to set the position.

The first thing to do there is to WAIT for a frame to get rid of the animator oppression :slight_smile: and the set the desired position.

In code :

IEnumerator SetPosition(){
Vector3 destination = new Vector3 (18f, 5f, 0);
yield return null;
transform.position = destination;
}

public void OnAnimationFinished(){
GetComponent ().enabled = false;
StartCoroutine (SetPosition ());
}

Well, to me it seems to much work for a (common?) task like this.
Am i missing something?

Thanks!

Use code tags when posting code!

If you want to change the transform after the animation has done things, you have to do that in LateUpdate. In the context of your Coroutine, that would mean yield return WaitForLateUpdate(), instead of yield return null;

What exactly is it you’re trying to do? Teleport to a specific position when the animation is finished?

1 Like

Thanks for the reply (and thanks for addressing me to code tags).

I can not find WaitForLateUpdate, there is only WaitForFixedUpdate and it is not the same, i know.

The real implementation of my Coroutine is different from the one i posted, basically i implement a tweening (i use DOTween) to move my object from the position given at the end of the animation clip and the destination vector3.

Something like that:

    IEnumerator SetPosition(Vector3 destination, float time){

        // ???
        yield return WaitForLateUpdate();

        transform.DOMove (destination, time).SetEase (Ease.InOutQuad);
       
        // other tweenings here...

    }

What do you think of the general idea?

I was sure there was a WaitForLateUpdate! Seems I was wrong, there’s a WaitForEndOfFrame, but that happens after rendering so you might as well just wait for the next frame. That’s probably not too bad.

What’s the problem with the disabling the animator solution? The first frame after the animation even has fired, the animator will set the position, yes, but after that the tweening engine should be setting it. Do you get a bad jitter or something if you do:

animator.enabled = false;
transform.DOMove (destination, time).SetEase (Ease.InOutQuad);

?

Disabling the animator works, no jitter or other shenanigans.

I wrote this post to ask if this solution was looking hacky or not.
For what you’re saying i understand that it is not, so thanks!