Search Unity

[Mecanim 5 & Blend Tree] Animation event called twice

Discussion in 'Animation' started by Deleted User, Apr 14, 2015.

  1. Deleted User

    Deleted User

    Guest

    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

    http://forum.unity3d.com/threads/mecanim-4-3-animation-event-sent-twice.213830/

    @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.
     
    Last edited by a moderator: Apr 14, 2015
  2. CDF

    CDF

    Joined:
    Sep 14, 2013
    Posts:
    1,313
    Yes this is also happening to me as well, unity 5.0.1
     
  3. Deleted User

    Deleted User

    Guest

    Just finished updating to the last Unity version and still happening the same :(
     
  4. Mecanim-Dev

    Mecanim-Dev

    Joined:
    Nov 26, 2012
    Posts:
    1,675
    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.
     
  5. Deleted User

    Deleted User

    Guest

    Thanks for your reply. Sorry but I don't really know understand what you need... How can I log the bug?
     
    Last edited by a moderator: Apr 14, 2015
  6. Mecanim-Dev

    Mecanim-Dev

    Joined:
    Nov 26, 2012
    Posts:
    1,675
    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,
     
  7. Deleted User

    Deleted User

    Guest

    Hi @Mecanim.Dev. Thanks again for your help :)

    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).
     
    theANMATOR2b likes this.
  8. Mecanim-Dev

    Mecanim-Dev

    Joined:
    Nov 26, 2012
    Posts:
    1,675
    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
    http://docs.unity3d.com/ScriptReference/AnimationEvent-animatorStateInfo.html
    http://docs.unity3d.com/ScriptReference/AnimationEvent-animatorClipInfo.html

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

    Code (CSharp):
    1. class MyClass : MonoBehaviour
    2. {
    3.     void LateUpdate()
    4.     {
    5.         if (doProcessFloatEvent)
    6.         {
    7.             // Do handle animation event
    8.             doProcessFloatEvent = false;
    9.         }
    10.     }
    11.  
    12.     // In this case you delay your animation event processing in LateUpdate
    13.     void MyFloatEventCallback(float value)
    14.     {
    15.         doProcessFloatEvent = true;
    16.     }
    17.  
    18.     // In this case you choose event based on the clip weight
    19.     void MyAnimationEventCallback(AnimationEvent evt)
    20.     {
    21.         if (evt.animatorClipInfo.weight > 0.5)
    22.         {
    23.             // Do handle animation event
    24.         }
    25.     }
    26. }
    27.  
    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
     
  9. Deleted User

    Deleted User

    Guest

    :oops::oops::oops:

    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... :)

    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!!
     
    phobos2077, Adngel_ and theANMATOR2b like this.
  10. Razouille

    Razouille

    Joined:
    Jan 25, 2013
    Posts:
    44
    Sorry but since the 5.2 update this doesn't work anymore, as i explain on this thread : http://forum.unity3d.com/threads/me...iple-events-in-unity-5-2.353876/#post-2288309
    If you're still there it would be nice if you could take a look :)
     
  11. NeilW

    NeilW

    Joined:
    May 29, 2014
    Posts:
    40
    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.
     
  12. RakNet

    RakNet

    Joined:
    Oct 9, 2013
    Posts:
    315
    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.
     
    Ultroman likes this.
  13. PSchwilden

    PSchwilden

    Joined:
    Dec 9, 2016
    Posts:
    4
    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!
     
  14. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    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.
     
  15. echannellink

    echannellink

    Joined:
    Sep 18, 2018
    Posts:
    1
    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);
    }
    6. Increase the weight of the Shoot Layer to 1 from the setting icon

    7. On your
    void Update()
    {
    StartCoroutine(ShootandPose());
    }
     
  16. Megahertzs

    Megahertzs

    Joined:
    May 18, 2020
    Posts:
    2
    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).

    Forum.png
     
  17. CaseyHofland

    CaseyHofland

    Joined:
    Mar 18, 2016
    Posts:
    613
    Ariachnide and CiroContns like this.