04-01 Directional Basics

Location: Assets/Plugins/Animancer/Examples/04 Directional Sprites/01 Directional Basics

Recommended After: Basic Movement

Learning Outcomes: in this example you will learn:

How to organise animations in groups of up/right/down/left.

How to use Directional Animation Sets.

16x16 Mage
Created by saint11
CC0 Licence

This example demonstrates how to implement a character that can move in 4 directions (up/right/down/left) using simple data structures and reusable code.

Summary

Overview

The general code structure is very similar to previous examples, but it uses Directional Animation Sets instead of directly referencing individual AnimationClips:

Fields

Where the other examples directly reference individual AnimationClips or use Transitions, this time we are using Directional Animation Sets which are ScriptableObject assets that contain references to multiple AnimationClips.

We also need to store the direction the character is facing when they move so that when they stop they can still play the correct Idle animation to continue facing in that direction. Having this as a Serialized Field allows us to determine which direction the character will be facing on startup as well as in Edit Mode.

DirectionalBasics Script DirectionalAnimationSet Asset
[SerializeField]
private AnimancerComponent _Animancer;

[SerializeField]
private DirectionalAnimationSet _Idles;

[SerializeField]
private DirectionalAnimationSet _Walks;

[SerializeField]
private Vector2 _Facing = Vector2.down;

If you have Inspector Gadgets Pro, you can use its Nested Object Drawers feature (by clicking on the foldout arrows) to see and modify the details of the referenced asset without needing to actually go and select that asset:

Playing

Since we know which direction we are _Facing, we can have a method that takes any DirectionalAnimationSet, gets the animation for that direction from the set, and plays it like any other animation:

private void Play(DirectionalAnimationSet animations)
{
    var clip = animations.GetClip(_Facing);
    _Animancer.Play(clip);
}

Controls

This example controls the character movement using the WASD Keys, which is implemented by the Example Input script:

private void Update()
{
    var input = ExampleInput.WASD;

If the player is trying to move, we store that input as the direction they want to be _Facing:

    if (input != default)
    {
        _Facing = input;

Then we can pass the _Walks animation set into the Play method so that it will play the appropriate animation for that direction:

        Play(_Walks);

Since this example uses simple Sprite animations, we can easily allow the character to run by increasing the animation speed when the player holds Left Shift. We could have had our Play method return the AnimancerState it gets from _Animancer.Play, but we can also just access it using _Animancer.States.Current:

        var isRunning = ExampleInput.LeftShiftHold;
        _Animancer.States.Current.Speed = isRunning ? 2 : 1;
    }

Note that changing the AnimancerState.Speed is a Pro-Only Feature. Animancer Lite allows you to try it out in the Unity Editor, but it will do nothing in runtime builds unless you purchase Animancer Pro.

Finally, we can simply return to one of the _Idles when the player stops trying to move. Note that we are not setting the _Facing direction in this case, so it will still be facing in the last direction it moved:

    else
    {
        Play(_Idles);
    }
}

This example does not actually move the character around since is just demonstrating the basics of Directional Animation Sets, but the Directional Character example does demonstrate movement.

Edit Mode

If we were to make another character with some different DirectionalAnimationSets, it would use those animations at runtime but it would not actually show the correct sprite in Edit Mode unless we re-assign it manually. Fortunately, Animancer allows you to easily apply and even play animations in Edit Mode. All we need to do it use MonoBehaviour.OnValidate to call AnimancerUtilities.EditModeSampleAnimation:

#if UNITY_EDITOR
private void OnValidate()
{
    // We need to null-check the _Idles to prevent GetClip from throwing an exception if it's not assigned yet.
    // But EditModeSampleAnimation will take care of null-checking the AnimationClip and _Animancer.
    if (_Idles != null)
        _Idles.GetClip(_Facing).EditModeSampleAnimation(_Animancer);
}
#endif

The #if UNITY_EDITOR isn't actually necessary because Unity will not call OnValidate at runtime anyway, but this allows us to be clearer about what the code is doing.

Also note that this did not work properly before Unity 2018.3 due to a bug.

Conclusion

Click here to see the full DirectionalBasics script.

using Animancer;
using UnityEngine;

public sealed class DirectionalBasics : MonoBehaviour
{
    [SerializeField] private AnimancerComponent _Animancer;
    [SerializeField] private DirectionalAnimationSet _Idles;
    [SerializeField] private DirectionalAnimationSet _Walks;
    [SerializeField] private Vector2 _Facing = Vector2.down;
    \
    private void Update()
    {
        var input = ExampleInput.WASD;
        if (input != default)
        {
            _Facing = input;

            Play(_Walks);

            var isRunning = ExampleInput.LeftShiftHold;
            _Animancer.States.Current.Speed = isRunning ? 2 : 1;
        }
        else
        {
            Play(_Idles);
        }
    }

    private void Play(DirectionalAnimationSet animations)
    {
        var clip = animations.GetClip(_Facing);
        _Animancer.Play(clip);
    }

#if UNITY_EDITOR
    private void OnValidate()
    {
        if (_Idles != null)
            _Idles.GetClip(_Facing).EditModeSampleAnimation(_Animancer);
    }
#endif
}

Now we can create more DirectionalAnimationSets and reuse the same script for more characters.

16x16 Animated Critters
Created by patvanmackelberg
CC0 Licence

Antifarea's RPG sprite set 1
Created by Antifarea
CCBY Licence
Not included in Animancer due to Asset Store licensing restrictions.

Sub-Assets

Since the there are lots of animations in this example and they are each only used by a single DirectionalAnimationSet, the Drag and Drop Sub-Assets feature of Inspector Gadgets Pro was used to turn the animations into sub-assets of the set in order to organise them a bit better. This has absolutely no effect on how the animations can be used, it's purely for organization during development.

What Next?

Example Topic
Directional Character Uses Directional Animation Sets in a more complex character.