<< Application Icon for Mac Store submission | Home | All your pixel art games come hang with us! >>

Unity 3D: Tips on combining treadmill animations and animations with baked in translation.

A stream of consciousness treatise (aka a messy mind blatt)

Treadmill Animations

The most obvious way to combine character animation and movement in Unity 3D is to use "treadmill" style animations. The character is animated to walk, run or otherwise perambulate on the spot. Actual world space movement is typically controlled via script or code. This is straight forward enough but one has to take care to setup the control code to translate the character at a rate which visually corresponds to the animation. Visible foot skating is the most common obvious side effect.

Complex Activities

Sometimes with more complex animations and interactions with the world it is very difficult to get animations to look like the characters are properly interacting with the world. Poor hand, hand or foot placements or character/world geometry intersections are likely symptoms. This kind of problem is most commonly solved using animations that include translation of the root node and the animation played is matched with specific world geometry and or props.

Typical examples of activities that might require such techniques include climbing, swinging and parkour style animations.

Trying to have the best of both world

Triggers to signal change of state. Standard sized interactive world object. Play animation with root node translation/animation On animation end take note of the world space location and apply this position to the root of the GameObject. When treadmill animations take over again it will should fine.

Animation Event

Animation events allow functions to be called at marked points during an animation. The canonical example of a use for this is timing the sound of footsteps during a walk cycle animation. The animation may be several seconds long but footfalls occur at specific time points.

AnimationEvent animationEvent = new AnimationEvent();
animationEvent.functionName = "OnAnimationEvent";
animationEvent.time = 0.4f;
animation.GetClip("animationName").AddEvent(animationEvent);
Animation Event Receiver

One little gotcha with Unity animation events is that the function that gets called by the animation event must reside in a script that is attached to the GameObject that is running the animations. Often this is the case so it just works but sometimes this is not the case. To make this a little easier for myself I usually use something like an AnimationEventReceiver script and attach it to GameObjects running the animation that will be firing my event. The receiver script acts as a proxy object that will then call my real method doing the work via it's delegate. The AnimationEventReceiver looks like:

public class AnimationEventReceiver : MonoBehaviour {
    public const string FUNCTIONNAME = "OnAnimationEvent";
    public delegate void AnimationEventDelegate(AnimationEvent animationEvent);
    private AnimationEventDelegate _callback;
    public AnimationEventDelegate callback { 
      set { _callback = value; }
    }
    public void OnAnimationEvent(AnimationEvent animationEvent) {
       if (_callback == null) {
          Debug.Log("AnimationEventReceiver callback delegate has not been set for animation event");
	  return;
       }
       _callback(animationEvent);
    }
}

Using this is something like

AnimationEventReceiver animEventReceiver = gameObject.AddComponent();
animEventReceiver.callback = delegate(AnimationEvent e) {      
   OnEventMethod();
};

This can be used from just about anywhere as our AnimationEvenReceiver exists on the animated GameObject to receive our AnimationEvent message