Huy Minh Ha

Software development, Tech and other stuff

Mon 02 January 2017

Using Unity Mecanim animation system

Posted by Ha.Minh in Unity   

See unity-mecanim for sample code of this article

Mechanim basics

animation parameters

  • Animation Parameters are variables that are defined within an Animator Controller that can be accessed and assigned values from scripts. This is how a script can control or affect the flow of the state machine.
  • Parameters can be assigned values from a script using functions in the Animator class: SetFloat, SetInt, SetBool, SetTrigger and ResetTrigger
  • Mecanim Animation Parameter Types: Boolean vs. Trigger
  • Parameters can also be controlled in animation using Curve and read in script
    • You cannot control an Animation parameter from both Curve and Script, so you have to structure your code correspondingly.

Root motion, Blend Tree

Layer, Layer Mask

  • Layer Usages (Animator Controller Layers)
    • Additional layer for handling different body parts while the base layer handles the base movement, such as: wave hand while moving
    • Blending mode can be: Override or Additive. Normally Override will be used because using Additive can be highly unpredictable unless you're an advanced animator. (advanced animation)
    • Blend additional movement based on character state such as: heavy breathing when tired
    • Sync layer when you have a set of animation for when the character state changes such as: wounded animations
  • Avatar Mask(Avatar Masks)
    • Could be set in animation to see the effect of Masking only part of the body
    • Normally apply to layer which controls part of the body (advanced animation)

Equip weapon

  • Equip immediately without animation
    • For models created in Unity
      • Create weapon holder node
      • Attach the weapons to it
      • Hide/Unhide the correct weapon when switching weapon
    • For models created outside Unity
      • Find the correct node in the model OR create a weapon holder node like before
      • Attach the weapons to it
      • Hide/Unhide the correct weapon when switching weapon
  • Equip with equip/unequip animations. All weapons are treated the same when equipped (Sword equipping)
    • Create equip/unequip animation for each weapons
    • Using layer/layer mask to blend the equip/unequip animations, masking only the necessary parts of the body, such as the arm movement
    • Using Animation Event to set value to flags such as: sword_equipped, sword_unequipped
    • Attach the corresponding weapon using Animation Event calling functions and/or flags
  • Weapons affect whole animation when equiped (Applied Mecanim : Character Animation and Combat State Machines)

Using mechanim as state machine

  • Mecanim as generic state machine
  • Reusing animator controllers with AnimatorOverrideController
  • Applied Mecanim : Character Animation and Combat State Machines
    • A character with
      • 8 weapon types
        • 9-12 ground attacks
        • 5 aerial attacks
        • 3 defensive maneuvers
      • 4 throwable items
      • 6 classes of magic each with 3-6 abilities
      • Basic locomotion, jump, hit react, death
    • One way is to use SubStateMachine, with several depth layers
    • An alternative organization is to use BaseLayer with Overrides Layer and Additive Layer
  • Leveraging Unity 5.2's Advanced Animation Features
    • You can manage all transitions between attacks manually
    • Or you can use a blend tree. This is slightly better. One problem is if you change the Blend parameter while playing animation, it will change the animation immediately.
    • Solution in Unity 5: StateMachineBehaviour on a State. This way you can have code that run at the Start or End of your blendtree.
    • You could also have StateMachineBehaviour on a StateMachine. Then you can override OnStateMachineEnter and OnStateMachineExit functions
    • When the SubStateMachine is a sequence of animations, you can have code on OnStateMachineEnter to equip weapon
    • Can also check for Input in StateMachineBehaviour

Best Practices

  • Animation events not firing when the event is near the endframe, so either use a third party event dispatcher, or use StateMachineBehaviour.

  • Use custom class to cache animation event

    • You might catch animation events using a general event handler function such as OnAnimationEvent (AnimationEvent), however this might not be the best solution since you will have to do a switch case in your main logic class. This will make the main logic class (e.g. Enemy, Player) knows too much about the flow to handle animation event. Also you might not be able to reuse common code.
    • A better way is to have a generic custom class to handle animation event, e.g. AnimatorHandler. This class will have most common function such as OnAnimationStart, OnAnimationEnd, OnAnimationUpdate. You can pass custom handle functions in as callback if you need to. This class also has common utility function such as getting current state name, check if any animation is playing etc.
  • When importing animations, make sure to Bake into pose the part where you don't want to move by Root motion. Also use Offset to fix Average velocity not zero problems, e.g. walking animation that has a X speed

  • Change the animation speed of specific layer

  • Use int parameter instead of boolean or trigger. This way you can use AnyState to transition using condition such as skill=1, then when entering the mecanim state we set it to another number immediately Applied Mecanim : Character Animation and Combat State Machines
  • Use substate to simplify your state machine. However, becareful when constructing AnyState transition to deeper substate, since AnyState is global. In this way, we can ignore the immediate substate and only care about the final subtate. We use the most specific condition, such as skill=1 and subskill=2 to trigger the final substate from AnyState. This way we don't have to configure transition to immediate substate and only care about the final state
  • Use SMB: Applied Mecanim : Character Animation and Combat State Machines
    • SMB makes sure that OnStateMachineExit is called when exiting a state. Putting a animation event at the end of an animation cannot ensure that for 2 reasons: The animation might be forced to switch in the middle or the animation event might not fire because the animation is played too quickly
  • Running an animation completely before transitioning back

    • Make sure Exit time is 1.00, with FixedDuration unchecked.
  • How to Run the death animation then destroy GameObject

    • Use a timer. This is quite a robust solution but maybe not visually correct in some cases, i.e. the animation might be stopped too soon.
    • Use animation event. Add an Exit event to the animation at the last frame. This is not very robust, since Unity might skip Animation event
    • Use auto transition to a fake after death state. Then use StateMachineBehaviour to detect when we exit the Death state. This is also a robust solution, but requires you to modify the structure of the Animator.
  • How to transition out of a substate machine (Using substate machine)

    • Using Up node: Transition to state or StateMachine
    • Using Entry/Exit nodes: Transition to/from StateMachine. This facilitates better reusability
    • Try to only use one way

    
 
 

Comments