How to Set Up Unity Character Animation for a 3D Platformer

If your 3D platformer character moves but stays in a fixed pose, Unity character animation is the next piece to connect. With experience teaching coding and game development across a catalog of over 400 courses, Zenva can guide you through the link between player input and character visuals. In this walkthrough, you will add smooth rotation, then connect idle, moving, and jump animations to the player controller.

This tutorial assumes you have Unity installed, know basic C#, and are using the supplied player assets and an existing PlayerController.cs with moveInput and IsGrounded().

Download Project Files

The project files and full project are available through the course included in the Unity Game Development Mini-Degree. Follow the full guided path there, or keep reading to work through the rotation and animation setup in this free tutorial.

Make a Complete Card Battler in Godot e1788415191322 - How to Set Up Unity Character Animation for a 3D Platformer
FREE GODOT COURSE
LEARN GODOT, UNITY, UNREAL & MORE
ACCESS FOR FREE
AVAILABLE FOR A LIMITED TIME ONLY

Rotate the Player Toward the Movement Direction

Start by making the character face the direction of travel. Right input should turn it right, upward input should turn it away from the camera, and downward input should turn it toward the camera.

Unity Game view showing the player character always facing forward on a gray platform, illustrating the starting problem before rotation is implemented.

Setting Up the Update Function

The rotation in this setup is a visual change rather than part of the physics simulation. Put it in Update, which runs every rendered frame, instead of FixedUpdate.

Open PlayerController.cs and add this method beneath FixedUpdate:

void Update ()
{

}

Understanding Rotation in Unity

Select the Player object and look at its Transform component in the Inspector. The X, Y, and Z rotation values are displayed in degrees. To turn the character left or right, you will change its Y-axis rotation.

Unity Inspector panel showing the Transform component and Rotation fields of the Player GameObject, alongside the Scene view with the character on a platform.

Calculating the Target Angle

The existing moveInput variable is a Vector2. Its X component represents left/right input, while Y represents forward/back input. You need to convert that direction into an angle for the character’s Y rotation.

Mathf.Atan2 returns the angle between the positive X-axis and a point defined by its two arguments. For this setup, pass moveInput.x first and moveInput.y second to map WASD input to the correct facing direction.

The result is in radians. Multiply it by Mathf.Rad2Deg to get degrees, then apply it through transform.eulerAngles:

void Update ()
{
    float targetAngle = Mathf.Atan2(moveInput.x, moveInput.y) * Mathf.Rad2Deg;
    transform.eulerAngles = new Vector3(0, targetAngle, 0);
}

Save the script and press Play. The character now snaps to face each movement direction, including diagonals.

Unity game view with the player character rotated to face a diagonal direction, and the Inspector showing the updated Y rotation value after the first rotation implementation.

Preventing Rotation Snap-Back

When you release the keys, this first version snaps the player back to zero degrees. To keep the last facing direction, skip rotation when there is no movement input.

The vector’s magnitude is its length. When both components are zero, its magnitude is zero; when a movement key produces a non-zero component, the magnitude is greater than zero. Add an early return to Update:

void Update ()
{
    if(moveInput.magnitude == 0)
        return;

    float targetAngle = Mathf.Atan2(moveInput.x, moveInput.y) * Mathf.Rad2Deg;
    transform.eulerAngles = new Vector3(0, targetAngle, 0);
}

Save and test again. Releasing the movement keys now leaves the character facing its last direction.

Unity game view showing the player character holding its last rotation facing left after releasing movement keys, with the Inspector confirming the rotation value is maintained.

Adding Smooth Rotation

The character keeps its facing direction, but still snaps between angles while moving. Use Mathf.LerpAngle to interpolate toward each new direction. Unlike a regular Mathf.Lerp, it handles the angle wraparound from 359 degrees to 0 degrees.

Supply three arguments:

  • The current Y rotation, transform.eulerAngles.y, as the starting angle.
  • The calculated targetAngle as the destination.
  • Time.deltaTime * 50 as the interpolant, scaling the change by the elapsed frame time.

Store the interpolated value in angle and use it when setting the rotation:

void Update ()
{
    if(moveInput.magnitude == 0)
        return;

    float targetAngle = Mathf.Atan2(moveInput.x, moveInput.y) * Mathf.Rad2Deg;
    float angle = Mathf.LerpAngle(transform.eulerAngles.y, targetAngle, Time.deltaTime * 50);
    transform.eulerAngles = new Vector3(0, angle, 0);
}

Press Play to check the smoother turn. The multiplier 50 controls how quickly the character turns; a lower value such as 30 makes the turn more gradual, while a higher value makes it more responsive.

Unity game view in Play mode showing the player character with smooth rotation active, facing a diagonal direction confirmed by a non-snapped rotation value of approximately 176 degrees in the Inspector.

With the facing direction working, you can now replace the character’s fixed pose with animations.

Set Up Unity Character Animation With an Animator Controller

Your player needs an idle animation when standing still, a moving animation while running, and an in-air animation for jumping and falling. Begin with the supplied clips and the idle-to-movement state machine.

Finding the Animation Assets

In the Project window, open Assets > Models > Player. Alongside the Rogue_Hooded model, you will find Rig_Medium_General and Rig_Medium_MovementBasics. These FBX files contain the animation clips for the character.

Unity Project window showing the Assets/Models/Player folder with the Rig_Medium_General and Rig_Medium_MovementBasics animation rig assets alongside the Rogue_Hooded player model.

Select Rig_Medium_General and open the Inspector’s Animation tab to see clips such as Idle_A, Hit_A, Interact, PickUp, and spawn animations. Rig_Medium_MovementBasics contains clips such as Running_A, Running_B, walking variants, and jumps.

Unity Inspector showing the Animation tab for Rig_Medium_General, listing clips such as Idle_A, Hit_A, and Spawn animations with their start and end frames, and a preview pane at the bottom.

Previewing Animation Clips

Select a clip in the Animation tab and press the play button in the preview pane at the bottom of the Inspector. Hold the right mouse button and drag inside the preview to rotate the camera around the model and inspect the motion.

For this character, use Running_B from Rig_Medium_MovementBasics for movement and Idle_B from Rig_Medium_General for idle.

Unity Inspector showing the Animation tab for Rig_Medium_MovementBasics with the Running_B clip selected and previewed in the bottom panel, showing a humanoid figure in a running pose.

Creating an Animator Controller

An Animator Controller defines a state machine: animation states and the rules for moving between them.

Create an Animation folder inside Assets. Right-click inside it, choose Create > Animator Controller, and name the asset Player.

In the Hierarchy, select the Rogue_Hooded child under the Player GameObject. Drag the Player controller onto that model in the Inspector. This adds an Animator component linked to the controller.

The Animator Window

Double-click the Player controller to open the Animator window. Use the scroll wheel to zoom and the middle mouse button to pan around its state-machine grid.

The new controller starts with three nodes:

  • Entry: the green starting point for the state machine.
  • Any State: a teal node for transitions that can occur from any state.
  • Exit: a red node.

Unity Animator window for the newly created Player controller, showing only the default Entry, Any State, and Exit nodes on an empty grid before any animation states have been added.

Adding the First Animation State

Expand Rig_Medium_MovementBasics using the arrow beside it in the Project window. Drag Running_B onto the Animator grid.

The new state is orange, with an arrow from Entry. Orange marks the default state, so Running_B begins playing when this Animator starts.

Unity Animator window showing the Running_B state as an orange node connected from the Entry node, indicating it is the default animation state that plays when the game starts.

Save and press Play. The running animation plays even while the player stands still. That confirms the state is working, but you still need an idle state and conditions for switching.

Adding the Idle Animation State

Stop Play mode, expand Rig_Medium_General, and drag Idle_B onto the Animator grid. It appears gray and unconnected because Running_B is still the default state.

Unity Animator window showing two states: Running_B in orange (the current default) and Idle_B in grey (newly added but not yet set as default), with the Entry arrow still pointing to Running_B.

Right-click Idle_B and select Set as Layer Default State. It turns orange, and the Entry arrow moves to it. The character will now start in the idle animation.

Enabling Loop Time

If a clip plays once and stops, enable looping in its source asset. For Idle_B, select Rig_Medium_General, open the Animation tab, and select the clip. Enable Loop Time, then click Apply.

Repeat this for the clips you intend to use, including Running_B, so they repeat when they reach the end.

Unity Inspector showing the animation clip settings for Idle_B, with the Loop Time checkbox visible and unchecked. Enabling this makes the animation repeat continuously once it reaches its end.

Renaming States for Clarity

Select each state and use the name field at the top of the Inspector to rename Idle_B to Idle and Running_B to Moving. These names make the state machine easier to follow.

Creating Transitions

Right-click Idle, choose Make Transition, and click Moving. Then create the reverse transition from Moving to Idle.

You now have arrows in both directions, but neither has conditions yet. You need conditions to make these changes respond to gameplay.

Unity Animator window showing the renamed Idle state (orange) and Moving state (grey) with a transition arrow being drawn from Idle to Moving.

Adding a Parameter to Control Transitions

In the Animator window’s Parameters tab, click + and choose Bool. Name the parameter Moving.

This true/false value will control the transitions. The player script will set it to true when there is movement input and false when that input stops.

Unity Animator window with the Parameters tab open and the + dropdown showing parameter type options: Float, Int, Bool, and Trigger, with Bool about to be selected to create a Moving parameter.

Assigning Conditions to Transitions

Select the Idle to Moving arrow. Under Conditions in the Inspector, click + and set Moving to true.

Select the reverse arrow, from Moving to Idle, and add Moving equals false. The parameter now determines which transition can occur.

Testing the State Machine

Before adding code, test the parameter manually. Select Rogue_Hooded in the Hierarchy and press Play. A blue progress bar on Idle shows that it is active.

In the Parameters tab, check Moving to switch to the running animation, then uncheck it to return to Idle.

Unity Animator window in play mode showing the Idle and Moving states with bidirectional transition arrows, alongside the scene view with the Rogue_Hooded character standing on a platform.

If the change feels delayed, the Animator is waiting for the current animation to reach its exit point. Next, you will remove that wait and connect the parameters to the player script.

Drive Movement and Jump Animations From the Player Controller

The state machine is ready for input. First, make its transitions responsive, then connect it to PlayerController and add the airborne state.

Fixing Animation Transitions

Select the transition from Idle to Moving in the Animator window. By default, Has Exit Time is enabled, making the animation wait for a set duration before it can transition.

Unity Animator Inspector showing the Idle to Moving transition with Has Exit Time checked, before the setting is disabled.

Disable Has Exit Time so the transition can start as soon as Moving becomes true. The Animator still blends between animations. Expand Settings and set Transition Duration to 0.1 for a responsive change.

Unity Animator Inspector showing the Idle to Moving transition with Has Exit Time unchecked and Transition Duration set to 0.1 seconds.

Make the same changes to the Moving to Idle transition: disable Has Exit Time and set Transition Duration to 0.1.

Unity Animator Inspector showing the Moving to Idle transition with Has Exit Time unchecked and Transition Duration set to 0.1 seconds, with Moving false as the condition.

Both transitions should now react almost immediately when the movement parameter changes.

Connecting the Animator to the Script

Open PlayerController.cs and add a serialized reference to the Animator alongside the existing serialized fields:

[SerializeField]
private Animator anim;

[SerializeField] exposes the private field in the Inspector. Save the script, let Unity compile, and select the Player GameObject. The Player Controller component now has an Anim field.

Unity Inspector showing the Player Controller script component with the Anim field set to None, ready to have the 3D model assigned.

Drag the Rogue_Hooded child model into Anim to assign its Animator component.

In FixedUpdate, add this line after the existing velocity and jump calculations:

// Update the animation state.
anim.SetBool("Moving", moveInput.magnitude > 0);

This updates Moving every physics frame. When moveInput.magnitude is greater than zero, the parameter becomes true; with no movement input, it becomes false.

Unity Game view showing the 3D character on a platform, with the Inspector confirming the Anim field is assigned to Rogue_Hooded and movement animations are active.

Press Play and check that pressing and releasing movement keys switches between the idle and moving animations.

Adding the Jump Animation State

The character still uses idle or moving animations while airborne. In the Project panel, find Jump_Idle, drag it into the Animator window, and rename the new state Jump.

Unity Animator window showing the state machine with the Jump_Idle animation clip selected in the Project panel, ready to be dragged in as a new Jump state.

In the Parameters tab, click +, select Bool, and name the parameter InAir. This will track whether the character is airborne.

Unity Animator window showing the state machine with Idle, Moving, and Jump states, alongside the Parameters panel listing the InAir boolean parameter.

Configuring the Jump Transitions

Connect Jump to the other states with four transitions:

  • Idle to Jump
  • Jump to Idle
  • Moving to Jump
  • Jump to Moving

Unity Animator window showing the state machine with transitions between Idle, Moving, and Jump states, with the Idle to Jump transition selected in the Inspector.

For each transition, disable Has Exit Time and set Transition Duration to 0.1. Then set the conditions:

TransitionConditions
Idle to JumpInAir is true
Moving to JumpInAir is true
Jump to IdleInAir is false AND Moving is false
Jump to MovingInAir is false AND Moving is true

The two conditions on each outgoing Jump transition select the appropriate animation when the character lands, depending on whether movement input is still held.

Controlling the Jump Animation From Code

The existing IsGrounded() method returns true while the character is on the ground. In FixedUpdate, add this directly below the Moving setter:

anim.SetBool("InAir", !IsGrounded());

The ! operator reverses the boolean. When IsGrounded() is true, InAir becomes false. When the character is airborne and IsGrounded() is false, InAir becomes true.

The animation-update block in FixedUpdate now reads:

// Update the animation state.
anim.SetBool("Moving", moveInput.magnitude > 0);
anim.SetBool("InAir", !IsGrounded());

Save and press Play. Check for idle when standing still, moving when walking, and Jump while airborne, with smooth transitions between the three states.

Unity Game view with the 3D character on a platform, confirming all idle, moving, and jump animations are working correctly after the lesson setup.

Review Your Platformer Character Setup

Your character now turns toward movement and changes animation to match its grounded or airborne state. You have connected the main pieces of the setup:

  • Converted movement input into a Y-axis angle and smoothed it with Mathf.LerpAngle.
  • Kept the last facing direction when movement input stops.
  • Built Idle, Moving, and Jump states from the supplied animation clips.
  • Configured transition conditions and reduced delays with Has Exit Time and Transition Duration.
  • Driven the Moving and InAir parameters from PlayerController.cs.

Run the scene and check the full sequence: move in different directions, release the keys, then jump and land with and without movement input. This lets you see the rotation and animation transitions working together.

Continue building your Unity skills with the Unity Game Development Mini-Degree. Follow a structured, project-based path to connect individual mechanics like these into games of your own.

Did you come across any errors in this tutorial? Please let us know by completing this form and we’ll look into it!

FREE COURSES
Python Blog Image - How to Set Up Unity Character Animation for a 3D Platformer

FINAL DAYS: Unlock coding courses in Unity, Godot, Unreal, Python and more.