05 Hybrid Basics

Difficulty: Intermediate

Location: Assets/Plugins/Animancer/Examples/01 Basics/05 Hybrid Basics

Namespace: Animancer.Examples.Basics

This example demonstrates how you can use the HybridAnimancerComponent to manage some animations inside an Animator Controller while also using other separate Animation Clips. The Hybrid example extends this concept.

Pro-Only Features are used in this example: HybridAnimancerComponent and the ability to play Animator Controllers in Animancer. Animancer Lite allows you to try out these features in the Unity Editor, but they are not available in runtime builds unless you purchase Animancer Pro.

The SimpleHybrid script simply exposes some public methods for various UI Buttons to call:

using Animancer;
using System;
using UnityEngine;

public sealed class SimpleHybrid : MonoBehaviour
{
    [SerializeField] private HybridAnimancerComponent _Animancer;
    [SerializeField] private AnimationClip _GolfSwing;
    [SerializeField] private AnimationClip _TennisForehand;

    public void SetIsWalking(bool value)
    {
        _Animancer.SetBool("IsWalking", value);
    }

    public void PlayRun()
    {
        _Animancer.Play("Run");
    }

    public void PlayTennisForehand()
    {
        _Animancer.Play(_TennisForehand);
    }

    public void PlayGolfSwing()
    {
        _Animancer.Play(_GolfSwing);
    }

    public void PlayController()
    {
        _Animancer.PlayController();
    }
}

Creating the Animator Controller

Creating the Animator Controller asset we need for this example is a relatively simple process:

  1. Right Click in the Project window and use the Create -> Animator Controller function. Give it a name (such as Basic Locomotion) and Double Click on it to open it in the Animator window:

  2. Right Click in the Animator window and use the Create State -> Empty function three times to create three states. Name them Idle, Walk, and Run (note that the capitalisation must match what you use in your scripts when referring to these states):

  3. Assign the appropriate animation to the Motion field of each state (Humanoid-Idle, Humanoid-Walk, and Humanoid-Run respectively):

  4. Go to the Parameters tab in the left panel and create a Bool parameter named IsWalking (again, capitalisation is important):

  5. Right Click on the Idle state and use the Make Transition function then click on the Walk state to set the destination of the transition. Do the same thing again to create a transition from Walk back to Idle. Select the Walk -> Idle transition, scroll down, and add a Condition so that it gets triggered when the IsWalking parameter is set to false. Do the same thing for Idle -> Walk for when the parameter is true:

  6. Select the character in the scene then drag and drop the Animator Controller you just created into the Controller field of the HybridAnimancerComponent (not the Controller field of the Animator component):

Walking

The Animator Controller has an IsWalking parameter which controls the transitions between its Idle and Walk states. Normally, that parameter would be controlled via Animator.SetBool, but when using a HybridAnimancerComponent it is controlled via that component instead:

[SerializeField] private HybridAnimancerComponent _Animancer;

public void SetIsWalking(bool value)
{
    _Animancer.SetBool("IsWalking", value);
}

The other methods in this example are set up to be called by UI Buttons, but this one is actually called by a Toggle which works slightly different. Instead of an On Click event like Buttons have, it has an On Value Changed event with a bool parameter to indicate what value it was set to. This means that when selecting which method you want it to call, the SetIsWalking method will appear twice:

Dynamic Bool Static Parameters
This is the one we want because it will pass the value of the Toggle component into the method. This one shows a toggle in the event itself and will pass that value into the method, regardless of the state of the Toggle component.

Note that if the Animator Controller is not playing (in the above video that happens when we play the Golf Swing animation because it is one of the Other Animations), then setting a parameter will not make it start playing. To do that, you need to call HybridAnimancerComponent.PlayController (which the bottom button does).

public void PlayController()
{
    _Animancer.PlayController();
}

Also note that while the Animator Controller is not playing, the Animator window will not show its details. So in the above video when it looks like the parameter is not being set that is not actually the case, it is being set but the Animator window simply isn't showing the runtime state of that Animator Controller.

Running

The Animator Controller doesn't have any transitions set up for the Run state, but you can still play it using HybridAnimancerComponent.Play (or CrossFade) where you would otherwise use Animator.Play (or CrossFade):

public void PlayRun()
{
    _Animancer.Play("Run");
}

Note that "Run" is the name of the state in the Animator Controller, not the AnimationClip played by the state (the clip is called Humanoid-Run). If you drag and drop an Animation Clip into an Animator Controller, it will create a state for that clip with the same name as it, but they can then be renamed independantly so you cannot rely on them having the same name.

You could call Play("Idle") or set up a transition to stop running, but in this example the only way to do so is to play one of the other separate AnimationClips so that it stops the Animator Controller and resets it to its default state (the orange highlighted Idle state). If you do not want it to reset like that, you can set the Keep State On Stop toggle to true in the Inspector (which sets the ControllerState.KeepStateOnStop property at runtime).

Other Actions

Some animations are not going to get used very often and thus do not need to be part of the character's main Animator Controller. For example, there might be an animation that a character can use to interact with a particular object which isn't used anywhere else in the game. So the main purpose of a HybridAnimancerComponent is to allow such animations to be played by directly referencing their AnimationClips in a script (the same way most of the other examples use Animancer):

[SerializeField] private AnimationClip _GolfSwing;
[SerializeField] private AnimationClip _TennisForehand;

public void PlayTennisForehand()
{
    _Animancer.Play(_TennisForehand);
}

public void PlayGolfSwing()
{
    _Animancer.Play(_GolfSwing);
}

The Hybrid example extends this concept to implement a character that can move around and a separate mini game which uses animations that the character does not otherwise know about. This means that you do not see those animations while working on the character's main movement mechanics so you do not need to worry about accidentally breaking an unrelated part of the game.