# Animating a Character

When animating a character, you should query the character's state and/or subscribe to its numerous events, feeding this information to your `AnimationController` parameters to ensure your animation stays perfectly in sync with the character's state, such as whether it is grounded, falling, jumping, etc.

> ECM2 does not require the use of animation or any specific animation techniques. You have the freedom to animate your characters using 'plain Unity code' or your preferred method.

In this example, we will animate the included **UnityCharacter** model, syncing its animator with the information provided by the `Character` class.

```csharp
/// <summary>
/// This example shows how to animate a Character,
/// using the Character data (movement direction, velocity, is jumping, etc) to feed your Animator.
/// </summary>

public class AnimationController : MonoBehaviour
{
    // Cache Animator parameters
    
    private static readonly int Forward = Animator.StringToHash("Forward");
    private static readonly int Turn = Animator.StringToHash("Turn");
    private static readonly int Ground = Animator.StringToHash("OnGround");
    private static readonly int Crouch = Animator.StringToHash("Crouch");
    private static readonly int Jump = Animator.StringToHash("Jump");
    private static readonly int JumpLeg = Animator.StringToHash("JumpLeg");
    
    // Cached Character
    
    private Character _character;

    private void Awake()
    {
        // Cache our Character
        
        _character = GetComponentInParent<Character>();
    }

    private void Update()
    {
        float deltaTime = Time.deltaTime;

        // Get Character animator

        Animator animator = _character.GetAnimator();

        // Compute input move vector in local space

        Vector3 move = transform.InverseTransformDirection(_character.GetMovementDirection());

        // Update the animator parameters

        float forwardAmount = _character.useRootMotion && _character.GetRootMotionController()
            ? move.z
            : Mathf.InverseLerp(0.0f, _character.GetMaxSpeed(), _character.GetSpeed());

        animator.SetFloat(Forward, forwardAmount, 0.1f, deltaTime);
        animator.SetFloat(Turn, Mathf.Atan2(move.x, move.z), 0.1f, deltaTime);

        animator.SetBool(Ground, _character.IsGrounded());
        animator.SetBool(Crouch, _character.IsCrouched());

        if (_character.IsFalling())
            animator.SetFloat(Jump, _character.GetVelocity().y, 0.1f, deltaTime);

        // Calculate which leg is behind, so as to leave that leg trailing in the jump animation
        // (This code is reliant on the specific run cycle offset in our animations,
        // and assumes one leg passes the other at the normalized clip times of 0.0 and 0.5)

        float runCycle = Mathf.Repeat(animator.GetCurrentAnimatorStateInfo(0).normalizedTime + 0.2f, 1.0f);
        float jumpLeg = (runCycle < 0.5f ? 1.0f : -1.0f) * forwardAmount;

        if (_character.IsGrounded())
            animator.SetFloat(JumpLeg, jumpLeg);
    }
}
```

As you can observe, this is standard Unity code that leverages the character's state information to control our animator.

## Root Motion

The `Character` class, includes built-in support for root motion.

## Utilizing Root Motion

To enable root motion, follow these steps:

1. Add the `RootMotionController` component to your model's `GameObject`. This `RootMotionController` is responsible for providing the animation's velocity, rotation, etc., to the `Character`.
2. Enable the `useRootMotion` property in the `Character`. This property can be toggled as needed.

Once a character is moved using root motion, the animation assumes complete control over the character's movement. This replaces all procedural movement, rendering properties such as `maxWalkSpeed`, `maxFallSpeed`, etc., irrelevant, as the character is entirely driven by the animation.

Worth noting, the character's ground constraint still applies when root motion is enabled. This implies that any vertical movement in your root motion-based animation won't function unless you explicitly disable this constraint. In such cases, it's advisable to assign the **Flying** movement mode, as it automatically disables the ground constraint and allows for vertical movement.

{% hint style="warning" %}
To enable vertical root motion movement, the character's movement mode must be set to **Flying**.
{% endhint %}

## Toggling Root Motion

This example demonstrates how to toggle root motion at run-time. In this case, enabling root motion only while the character is in the **Walking** movement mode.

```csharp
public class RootMotionToggle : MonoBehaviour
{
    private Character _character;
    
    private void OnMovementModeChanged(Character.MovementMode prevMovementMode, int prevCustomMovementMode)
    {
        // Allow root motion only while walking
        
        _character.useRootMotion = _character.IsWalking();
    }

    private void Awake()
    {
        _character = GetComponent<Character>();
    }

    private void OnEnable()
    {
        // Subscribe to Character events
        
        _character.MovementModeChanged += OnMovementModeChanged;
    }

    private void OnDisable()
    {
        // Un-Subscribe from Character events
        
        _character.MovementModeChanged -= OnMovementModeChanged;
    }
}
```

In this example, we utilize the `MovementModeChange` event, which is triggered each time the character changes its current movement mode, making it perfect this case.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/animating-a-character.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
