Search Unity

Mecanim Events going ballistic from blend trees.

Discussion in 'Editor & General Support' started by JasonB, Nov 20, 2013.

  1. JasonB

    JasonB

    Joined:
    Dec 29, 2010
    Posts:
    102
    I've got a blend tree set up with 4 directions and all 4 movement animations have footstep events assigned to them.

    When I play, the footsteps are going WILD. Sounds to me like it's trying to play the footstep sounds of every single walk animation in the blend tree as if they were all playing at once.

    I was previously using the Mecanim event third party add-on and never had this problem with an identical setup.
     
  2. JasonB

    JasonB

    Joined:
    Dec 29, 2010
    Posts:
    102
    Is this a known bug? Will it be fixed? It's of utmost importance to my project. I'm assuming any bug not listed in the "known issues" thread hasn't yet been acknowledged.
     
    Last edited: Nov 26, 2013
  3. SkoleRune

    SkoleRune

    Joined:
    Jul 29, 2013
    Posts:
    1
    I am having the exact same problem. I am just thinking about checking if the sound is already playing, but it is not a good solution....
     
  4. skalev

    skalev

    Joined:
    Feb 16, 2012
    Posts:
    264
    This issue is still un-resolved.

    Seems like unity flattens out the animation events and just plays them all, irrespective of the actual weight of the clip.
     
  5. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,655
    How should it behave? If you've got one animation blended to 0.1 and another to 0.9, should it play events from both? What about when they're 0.5 and 0.5?

    I've always used curves for exactly this reason - the curves blend across the animations in the same way as any other curve, and I use zero-crossings to indicate when footfalls occur. The result is zero-crossings that match the foot's actual movement and so are synchronized to the animation no matter what blend situation it's in.
     
  6. JasonB

    JasonB

    Joined:
    Dec 29, 2010
    Posts:
    102
    Create 2D animations and you'll very quickly see where this system breaks down.

    Unity clearly knows which animation has dominance at any given time but plays the events from animations that technically aren't playing. Again, make a blend tree for 2D animations and you'll see that animations play only when they're dominant.

    It shouldn't be too difficult to have an option for a blend tree to only play events from its current most dominant animation so that those of us making 2D games can still enjoy the organization/power of blend trees.

    Making 2D animations without using blend trees gets very tricky, especially when you have 4 directions and 2 different movement speeds (walking and running) to worry about.

    If there's a better way to accomplish what we're trying to do though, I'm all ears. All I care is that I have a working solution.
     
  7. 0tacun

    0tacun

    Joined:
    Jun 23, 2013
    Posts:
    245
    I encounterd the same issue. Still no solution besides using curves?
     
  8. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Well you could check his foot transform is close to the floor, and set a no duplicate flag, ie don't do it in mecanim. This would be a horrible workaround I know.

    I'm not sure how it would work when blending between two poses. I think it probably should have conditionals in this case.
     
  9. 0tacun

    0tacun

    Joined:
    Jun 23, 2013
    Posts:
    245
    Thank you Hippo, you gave me another idea for a workaround with a timer:

    Code (JavaScript):
    1.     private var canEmit : float = 0.1;
    2.          
    3. function Footstep() {
    4.     if( canEmit <= 0.0 ) {
    5.     var rotation : Quaternion = Quaternion.LookRotation(-myTransform.forward, myTransform.up);
    6.     var position : Vector3 = myTransform.position +  myTransform.forward * -0.5;
    7.     position.y = myTransform.position.y + 0.2;
    8.     ParticleManager.instance.EmitParticle( "particleFootstep", position, rotation, 0.4 );
    9.  
    10.  
    11.     mySoundManager.EmitSound( 0.1, 0.2, "footstep", 5.0 );
    12.     canEmit = 0.1;
    13.     } else {
    14.         decreaseTimer();
    15.     }
    16. }
    17.  
    18. function decreaseTimer(){
    19.     while( canEmit > 0.0 ) {
    20.         canEmit -= Time.deltaTime;
    21.         yield;
    22.     }
    23. }
    It killed the second doubled footstep as expected., but I have to see how stable this workaround is.
     
  10. jasonoda

    jasonoda

    Joined:
    Sep 7, 2012
    Posts:
    67
    Here's how I solved the footstep problem:

    1. Make 2 different function calls. One for forward steps, one for side.
    2. On your forward & backward animations, put a call to the forward function.
    3. On you side animations, put a call to your side function.
    4. Set up your input so you can measure the side speed and forward/backward speed of your character.
    5. use: if(Mathf.Abs(forSpeed)>Mathf.Abs(sideSpeed)){ in the forward function and the opposite in the side function
    this way it only calls the footstep if the input is pointing to it.

    after that for safety, you may also want to add in a delay factor.
     
  11. itsmars

    itsmars

    Joined:
    Oct 1, 2013
    Posts:
    1
    I made a video about how to get around this problem. Instead of trying to use Animation Events, use Curves instead! Check out my video for a detailed explanation.
     
    MarekUnity and theANMATOR2b like this.
  12. Pnvanol

    Pnvanol

    Joined:
    Jan 11, 2016
    Posts:
    116
    video not available
     
  13. apatton

    apatton

    Joined:
    Sep 7, 2013
    Posts:
    8
     
  14. giuliano-marinelli

    giuliano-marinelli

    Joined:
    Mar 3, 2013
    Posts:
    3
    Great Solution!
    Put my example code here:

    Code (CSharp):
    1.     void FootForward() {
    2.         if(Mathf.Abs(turnAmount) < Mathf.Abs(forwardAmount)) {
    3.             audioSource.clip = footSound;
    4.             audioSource.Play();
    5.         }
    6.     }
    7.  
    8.     void FootSide() {
    9.         if(Mathf.Abs(turnAmount) > Mathf.Abs(forwardAmount)) {
    10.             audioSource.clip = footSound;
    11.             audioSource.Play();
    12.         }
    13.     }