Unity Basics: Animator — Part 2

How to edit the Animator Controller.

--

What Is an Animator?

The Animator is a core component of Mecanim, one of the animation systems provided by Unity.

In Part 1, we explored how to create or modify animation clips before using the Animator. Continuing in Part 2, we will look into how to edit the Animator Controller.

What is an Animator Controller?

Animator View

The Animator Controller is a Unity asset that stores information built by using a State Machine. This State Machine defines animations for a specific character or game object in individual states and sets up transitions between these states. You can edit these states and transitions through the Animator View, which is essential for utilizing the Animator component.

How to Edit the Animator Controller?

To edit the Animator Controller, you need to open the Animator View. Here’s how you can open the Animator View:

  • Double-click on the Animator Controller to open it.
  • Open it through the menu by going to Window → Animation → Animator

What is a State?

Generally, a character is always performing some type of action. These actions vary by game but typically include standing, walking, running, rolling, jumping, etc. In the Animator Controller, these actions are defined as specific “States” when they are being executed.

To create a state, you can drag and drop an animation clip into the Animator View, or right-click within the Animator View to create one.

Typically, a State is represented as a long rectangle in the Animator View. When you click on a State, you can view its options in the Inspector View.

  • Motion
    Motion refers to the animation clip or blend tree that will be executed while in this State.
  • Speed
    Speed is the speed multiplier applied when the Motion is played.
  • Speed Multiplier
    You can use a float type parameter to adjust the speed multiplier of a specific state.
  • Motion Time
    You can use a float type parameter to adjust the Motion Time of a specific state.
  • Transitions
    Transitions list all the transitions associated with this State
  • Solo — Solo mutes all other transitions in the list except for the selected transition.
  • Mute — Mute mutes the selected transition.

For more detailed information about the options for a State, click here.

What is a Default State?

The Default State is the first state that is executed when the Animator Controller is activated. The first state added automatically becomes the Default State. If you want to set a different state as the Default State, you can do so by right-clicking on the desired state and selecting it.

What is Any State?

“Any State” is a special state that allows transitions to occur from any current state within the Animator Controller, as long as the conditions specified for the transition are met. This state is kind of built-in feature, so it cannot be deleted. Additionally, transitions from a specific “State” to “Any State” are not possible.

Using “Any State” allows for convenient transitions between states without considering the previous state, which can simplify certain animation workflows. However, this can also make state management more challenging and lead to unintended transitions, so it should be used with caution.

What is a Parameter?

A Parameter is a variable used within an Animator Controller to dynamically adjust the conditions for transitions or the values of states. These parameters can be accessed by clicking on the tab located at the top left of the Animator View.

The types of variables provided by parameters are as follows:

  • float
  • int
  • bool
  • trigger

float, int, and bool function similarly to the basic types commonly used in programming. A trigger works like a bool but is a special parameter that resets automatically once it triggers a transition.

void AnimatorTest()
{
anim.SetInteger("attack_type", 1);
anim.SetFloat("move_speed", 0.2f);
anim.SetBool("is_alive", true);
anim.SetTrigger("jump");
    var attackType = anim.GetInteger("attack_type");
var moveSpeed = anim.GetFloat("move_speed");
anim.ResetTrigger("jump");
}

What is a Transition?

A Transition refers to the process of switching from one state to another within an Animator. In the Animator View, transitions are represented by arrows connecting one state to another.

To set up a transition, right-click on the starting state and select the state to which you want to connect. Even if the starting state and the next state are the same, multiple transitions can still be added.

Additionally, clicking on a specific transition allows you to see all transitions that go in the same direction. Options for each transition can be viewed and adjusted in the Inspector View.

  • Transitions
    Transitions” is a list of all transitions that share the same direction as the selected transition. Clicking on an item in this list allows you to view options for that transition.
  • Solo — Solo mutes all other transitions in the list except for the selected transition.
  • Mute — Mute mutes the selected transition.
  • Has Exit Time
    This setting ensures that the transition only occurs after the current state’s animation has progressed through the specified Exit Time. Exit Time is expressed as a normalized time; for example, 0 represents 0%, and 0.75 represents 75%.
  • Fixed Duration
    This setting determines whether the time required for the transition to complete should be set in normalized time (%) or seconds (s).
  • Transition Duration
    Depending on the Fixed Duration setting, this value blends the animation transition between the current and next state based on time (s) or normalized time (%). A lower value results in a shorter blending time, which can make the animation transition appear abrupt.
  • Transition Offset
    This sets the starting point of the animation for the next state based on normalized time. For instance, 0 represents 0%, and 0.35 represents 35%.

For more information about the options of Transition, click here.

You can assign a name to a transition, but by default, this field is left blank. If no name is given, the name of the transition will automatically be set to the format “current state → next state”.

Example

So far, we have reviewed all the essentials needed to use the Animator system. Now, let’s try an example where every time the mouse is clicked, a 3D character will alternate between three different dances.

public class AnimatorTest : MonoBehaviour
{
const int DANCE_COUNT = 3;

[SerializeField]
Animator _anim = null;

int _danceIndex = 0;

void Update()
{
if (!Input.GetMouseButtonDown(0))
return;

++_danceIndex;
if (DANCE_COUNT <= _danceIndex)
_danceIndex = 0;

_anim.SetInteger("dance", _danceIndex);
}
}

Frequently Asked Questions (FAQs)

Q. How can I make an animation clip loop?

When you select an animation clip, you can view its settings in the Inspector View, just like any other asset. To set the clip to repeat, simply change the Loop Time setting to true in this view.

Q. How can I optimize Parameter Calls?

When calling parameters in the Animator, you must pass the parameter name as a string. However, Unity internally converts this string into an integer using hashing. Since the related method is public, you can cache the hash value in advance for optimization.

// Before
void Play()
{
_anim.SetTrigger("play");
}

// After
static readonly int ANIM_PLAY = Animator.StringToHash("play");
void Play()
{
_anim.SetTrigger(ANIM_PLAY);
}

Q. How can I determine the current state that is playing?

In Unity’s Animator View, you can easily check the current state of a game object’s animator, determining this through code involves a more complex process.

bool Check(string stateName)
{
// Here, 0 represents the index of the Base Layer.
// We will discuss layers in more detail in Part 3.
var currentInfo = _anim.GetCurrentAnimatorStateInfo(0);

// Method 1
// Check using the name of the state.
// The name of the state is unique within the same layer.
if (currentInfo.IsName(stateName))
if (currentInfo.IsName(stateName))
return true;

// Method 2
// Check using the hashed value of the state's name.
// It is recommended to cache the hashed value beforehand and use it.
if (currentInfo.shortNameHash == Animator.StringToHash(stateName))
return true;

return false;
}

The “GetCurrentAnimatorStateInfo” method returns an “AnimatorStateInfo”, which is a struct. This means that the current state is only accurately guaranteed for the frame in which the method is called. Accuracy is not guaranteed for subsequent frames, so you need to call this method each time you perform a check.

Q. How can I trigger a specific state regardless of parameters?

Sometimes, you might not need to use the state machine, or you may want to ignore the relationship between states and transitions to directly trigger a specific state under special circumstances.

void PlayState(string stateName)
{
// Same as the examples above, you can also pass the hashed value as a parameter.
// This command plays the specified state.
_anim.Play(stateName);

// This plays the specified state in layer 0.
_anim.Play(stateName, 0);

// This plays the specified state in layer 0 starting from 20% of the state's duration.
_anim.Play(stateName, 0, 0.2f);
}

Q. How can I change the Animator Controller at runtime?

When developing a game, there might be various reasons why you need to change a specific character’s Animator Controller.

void ChangeAnimSet(RuntimeAnimatorController animSet)
{
_anim.runtimeAnimatorController = animSet;
}

However, it’s important to note that when you replace the Animator Controller, the current state of the Animator is lost, which can lead to unintended behaviors. For example, if you change the Animator Controller while in a running state, the running state will be lost and the character will switch to the default state of the new Animator Controller.

Q. How can I handle dynamically created game objects that are not affected by a character’s animator?

Let’s assume that Character A exists and uses various weapons, and A’s animations are designed to control these weapons. However, if Character A’s animator was initialized without these weapons present, dynamically generating weapons via scripts later might not be recognized by A’s animator.

This issue arises because when the animator is initialized, it collects information about all the game objects it can control. If the weapon did not exist at the time of initialization, the animator fails to recognize it later because it was not part of the initial data collection.

This can be resolved by requesting the animator to collect information again. By doing so updates the current state of the game objects under the animator’s control, including recognizing any newly created weapons.

void Rebind()
{
_anim.Rebind();
}

However, be aware that calling this method will cause the animator to collect information about all controllable game objects, which can lead to frame drops and reset the animator’s state. However, be aware that calling this method will cause the animator to collect information about all controllable game objects. This can lead to frame drops and will reset the animator’s state.

Therefore, when calling this method, be mindful of the game’s performance, and better use it only when the current state of the animator is critical. Additionally, as mentioned earlier, a reinitialized animator will restart its states from the beginning, which can lead to unintended behaviors.

Conclusion

So far, we have explored what an Animator is and how it can be used. In Part 3, we will cover Animator Layers and Humanoids. In Part 3, we will cover the Animator’s Layers and Humanoid features, so stay tuned!

Hopefully, this post has been helpful not only for those who are new to Animator but also for those who are already familiar with it.

<Related Posts>

Want more hyper-casual game development tips?
Click here and become Our partner today!

[Contact]
- E-mail: help@supercent.io
- Homepage:
corp.supercent.io

--

--

Supercent.official
Supercent Blog 슈퍼센트 블로그

Insights and tips to take your hyper-casual game to the top of the charts