[Mecanim 5 & Blend Tree] Animation event called twice

Hi guys, I have a important problem with Mecanim and Animation clips:

I’m developing a 2D top-down game (similar to Zelda’s) and I’m using several blend trees to handle animations (walking-up-right-down-left, etc) and everything looked fine until I needed some animation events in my clips. These events are sent twice and I don’t want to have to do a Boolean check every time to see If it has been called already this is going to get very messy.

For example: I have a “ShootRight” animation which sends an event at a certain frame of the animation that I use to “shoot” a projectile but right now, my character is shooting two projectiles and it’s annoying. Same thing for all the other animations (walking and raising duplicated dust prefabs when the character walks is another example)…

I’ve been searching all over the forum and I’ve found this

@Mecanim-Dev tells in this post from July 2014 that this was a known bug and would be fixed in Unity 5 (and the same appears here), but I’m developing the game in the last version (5.0.0f4 - Mac Version) and still having this problem (In fact, this issue happens with events called from every frame and not only the first one). Is this bug already fixed or I’m doing something wrong? Any solution?

Thank you for reading.

Yes this is also happening to me as well, unity 5.0.1

Just finished updating to the last Unity version and still happening the same :frowning:

All animation events bug are fixed right now according to our bug database. We did also add a unit test for all thoses case that were submited.

If you still have some issue with animation event please log a bug with your project.

Thanks for your reply. Sorry but I don’t really know understand what you need… How can I log the bug?

No worry it pretty easy and everybody can do it

In Unity Main menu click on Help/Report a Bug …
then follow the onscreen instruction, don’t forget to add your project and good repro step so we know how to reproduce the bug.

Once you are done you should get a confirmation email with your bug number.
PM your case number when you get it so I can do the follow up

Best regards,

Hi @Mecanim-Dev . Thanks again for your help :slight_smile:

I think I’ve found the problem, it’s not a bug itself but you guys should look into this. The same problem is set out in this post

The main issue here is that, with the use of a blend tree in a 2D game (with 2D animations), only the clip with the bigger weight is played but the others possibilities (other clips with a reduced weight) are also calling it’s events animations “in the curtains”… I totally understand this behaviour for a 3D game but is a really big problem when developing a 2D one and it should be fixed (or give an option to the developer to “disable” the clips with a less weight or “stick” only to the higher weighted one).

1 Like

Yes this is expected, all clip played by a blend tree will fire their animation events. Blend tree are expected to produce a smooth blend between clip.

I understand that in your case you only have 2d animation but this is not always the case, in the same clip you could animate any other property like material color so we cannot set all the weight of other clip in the blend tree to 0, this will create other issue.

We did add a few new member on the AnimationEvent class to allow you to determine from where the event come from

With this you can choose event based on the clip weight or you could delay you event processing in LateUpdate

class MyClass : MonoBehaviour
{
    void LateUpdate()
    {
        if (doProcessFloatEvent)
        {
            // Do handle animation event
            doProcessFloatEvent = false;
        }
    }

    // In this case you delay your animation event processing in LateUpdate
    void MyFloatEventCallback(float value)
    {
        doProcessFloatEvent = true;
    }

    // In this case you choose event based on the clip weight
    void MyAnimationEventCallback(AnimationEvent evt)
    {
        if (evt.animatorClipInfo.weight > 0.5)
        {
            // Do handle animation event
        }
    }
}

Another solution would be to use Direct Blend tree and control the weight of each motion with a script. This way you could control the weight and be sure that it always 100% thus playing only one clip

10 Likes

:sweat_smile::sweat_smile::sweat_smile:

I had no idea that the function called by the animation event could take an AnimationEvent as a parameter… With that, now I can check the clip weight without have to do “for-loops” in the array which is returned by animator.GetCurrentAnimatorClipInfo() to figure out which is the clip being played… I feel ashamed… :slight_smile:

You don’t know how helpful your comment was @Mecanim-Dev , thank you very very much mate.

Hope this post is useful for other developers with the same issue.

Cheers!!

3 Likes

Sorry but since the 5.2 update this doesn’t work anymore, as i explain on this thread : Mecanim blend tree throwing multiple events in Unity 5.2 - Unity Engine - Unity Discussions
If you’re still there it would be nice if you could take a look :slight_smile:

Yep - many thanks for the info - was also unaware of being able to get a callback with the AnimationEvent struct (not sure if that is new in 5?) - but certainly checking the weight > 0 has worked a treat for us.

Good grief, why is it not documented that the callbacks can have an AnimationEvent parameter??!! It would have saved me countless hours looping through all possible animations and guessing which one triggered the event.

1 Like

Hello!

I know I’m necro-ing and old thread but I had an additional question regarding the animation blend tree event weight. In @Mecanim-Dev example, he checks which event should be played by checking if the weight is > 0.5f, which assumes there can only be two motions active at the same time so the dominant motion will always have a weight bigger than 0.5f. However, in cases where there are more than two motions that are blended, checking if the weight is > 0.5f doesn’t work anymore.

Would there be a reliable way to get the currently dominant motion in a blend tree?

Thanks!

Blend Trees don’t give you any access to their internal details.

But if you check out Animancer (link in my signature), it has Mixers which are like Blend Trees without any stupid restrictions on what you can access so you can simply check the weight of each child. It also has a custom Animancer Event system which allows you to set events on the mixer itself (rather than the individual children) so that you only have one set of events which get triggered according to the blended time.

  1. Create a new layer apart from the one you have your blend tree, call it Shoot Layer

  2. Add your Shoot Animation to it

  3. Inbetween your Shoot Animation and Entry add Empty State as the default

  4. Connet your Shoot Animation and Empty State and add a trigger condition to only the one going from New State to Shoot Animation, name it shoot
    5 Add the below code
    private IEnumerator ShootandPose()
    {
    anim.SetLayerWeight(anim.GetLayerIndex(“Shoot Layer”), 1);
    anim.SetTrigger(“shoot”);
    yield return new WaitForSeconds(0.9f);
    anim.SetLayerWeight(anim.GetLayerIndex(“Shoot Layer”), 0);
    }

  5. Increase the weight of the Shoot Layer to 1 from the setting icon

  6. On your
    void Update()
    {
    StartCoroutine(ShootandPose());
    }

So, I know this is an old post, but I spent a couple days frustrated about this issue, and I found the solution to my problem. Essentially, I was trying to trigger an animation event from ONE of the 7 animations I have for my player’s attack animation. When I use a keyboard to set the blend tree parameters, it triggers only one animation event. But when I used a joystick to set the blend tree parameters, it triggers ALL 7 animation events.

I tracked down the weights of the playing blend tree animations and did the “Is this greater than .5”, but there are some times when my animations weren’t triggering correctly because, although it was the animation playing, it wasn’t greater than .5 on the weight. VERY FRUSTRATING.

The solution:

When setting the parameters, be sure to round to the nearest integer. I’m using Visual Scripting so it’s not exactly the same as C#; but the logic is the same. When setting the parameters for the Vector 2 of the joystick, use the “Round Int” node. This will ensure that the Animation Event will only trigger once.

(I’ll post this in all the forums I searched and didn’t see a solution).

WHAT?!?!?!?!

But I ask again:

8942760--1226859--the-what.jpg

3 Likes