01-02 Basic Movement

Location: Samples/01 Basics/02 Basic Movement

Recommended After: Quick Play

Learning Outcomes: in this sample you will learn:

How to respond to player input.

How to swap between different animations.

Summary

This sample demonstrates how to play a movement animation while you hold a key and return to an idle animation when you release the key.

The main logic looks like this:

protected virtual void Update()
{
    float forward = SampleInput.WASD.y;
    if (forward > 0)
    {
        _Animancer.Play(_Move);
    }
    else
    {
        _Animancer.Play(_Idle);
    }
}
  • This sample snaps between the animations instantly. Smooth blending is introduced in the Transitions sample.
  • Playing an animation that was already playing doesn't automatically restart it so you don't need to check if it was already playing and can simply keep telling it to play the one you want every frame.

Overview

The code structure looks similar to the Quick Play sample, but now it has two animations:

Input

To make the character respond to user input, we use an Update method (a MonoBehaviour Message which Unity will call every frame).

protected virtual void Update()
{

We won't be implementing full WASD movement in this sample, just W to move forwards. That can be done in two steps:

  1. Get the value of SampleInput.WASD, which is a Vector2 as explained in the Movement section on the Sample Input page.
  2. Take only its y value, which is a float representing forwards and backwards based on the W and S keys.

Those two steps only take a single line though:

    float forward = SampleInput.WASD.y;

That value will be:

  • 1 when W is held.
  • -1 when S is held.
  • 0 when neither button is held (or if both are held at the same time).

Animations

With the input value, we can use a simple if/else statement to decide which animation we want Animancer to play.

    ...// Update method continued from above.
    
    if (forward > 0)
    {
        _Animancer.Play(_Move);
    }
    else
    {
        _Animancer.Play(_Idle);
    }
}

When you tell Animancer to play an animation:

  • All other animations will be stopped (except if they're on different Layers).
  • If that animation was already playing, it will continue playing uninterrupted. The Basic Action sample explains how you can make it restart from the beginning if that's what you want.

The above code was written like that to keep it simple for beginners, but it could actually be compacted into a single line using a Ternary Conditional Operator like this:

    _Animancer.Play(forward > 0 ? _Move : _Idle);

Root Motion

By default, an Animator component will use Root Motion which allows animations to cumulatively move the character around the scene instead of moving them along a specifically animated path.

But if we let it do that here, the character will walk off into the distance and won't be able to get back because this sample doesn't include the ability to turn or move backwards.

We don't want that to happen so we just disable the Apply Root Motion toggle in the character's Animator component which will make the character run in place without moving forwards.

The Root Motion page goes into more detail about how this feature can be used.

Conclusion

Here's what the full script looks like:

using Animancer;
using UnityEngine;

public class BasicMovementAnimations : MonoBehaviour
{
    [SerializeField] private AnimancerComponent _Animancer;
    [SerializeField] private AnimationClip _Idle;
    [SerializeField] private AnimationClip _Move;

    protected virtual void Update()
    {
        float forward = SampleInput.WASD.y;
        if (forward > 0)
        {
            _Animancer.Play(_Move);
        }
        else
        {
            _Animancer.Play(_Idle);
        }
    }
}

Note how it doesn't need an OnEnable method because the first Update will take care of playing the appropriate animation before the first frame is rendered.

And here's what it looks like in action:

What Next?

Sample Topic
Basic Action Playing an Action animation when the user clicks and returning to Idle when it finishes.
Transitions Smoothly blending instead of instantly snappping between animations.