Character 2D Animation Tutorial

Learn how to create smooth 2D character animations using the Character 2D Animation Editor.

2D Animation System Overview

The Character 2D Animation Editor provides a complete solution for creating directional 2D character animations with automatic animator controller generation.

🎯 Multi-Directional

Support for 4-directional, 8-directional, or single-direction animations

📋 Sprite Sheet Support

Automatic sprite extraction from sprite sheets with customizable slicing

🎮 Animator Generation

Automatic creation of animator controllers with blend trees and transitions

👁️ Live Preview

Real-time animation preview with playback controls

Supported Animation Types

Idle

Character standing still, breathing or subtle movement

Frames: 1-4 Loop: Yes

Walk

Character walking at normal speed

Frames: 4-8 Loop: Yes

Run

Character running at increased speed

Frames: 4-8 Loop: Yes

Jump

Character jumping or in air

Frames: 3-6 Loop: No

Attack

Character performing attack actions

Frames: 3-6 Loop: No

Custom

Any custom animation you define

Frames: Variable Loop: Configurable

Character Setup

Step 1: Create Character GameObject

Start by creating your character GameObject with the required components:

  1. Create a new GameObject in your scene
  2. Name it appropriately (e.g., "Player", "Hero", "NPC")
  3. Add the required components:
    • SpriteRenderer - Displays the character sprite
    • Animator - Controls animation playback
    • Collider2D - For physics and interactions (optional)
    • Rigidbody2D - For physics-based movement (optional)
1"comment">// Example character setup script
2"keyword">public "keyword">class CharacterSetup : MonoBehaviour
3{
4 "keyword">void Start()
5 {
6 "comment">// Ensure required components exist
7 "keyword">if (GetComponent<SpriteRenderer>() == null)
8 gameObject.AddComponent<SpriteRenderer>();
9
10 "keyword">if (GetComponent<Animator>() == null)
11 gameObject.AddComponent<Animator>();
12
13 "comment">// Optional physics components
14 "keyword">if (GetComponent<Collider2D>() == null)
15 {
16 BoxCollider2D collider = gameObject.AddComponent<BoxCollider2D>();
17 collider.size = "keyword">new Vector2(0.8f, 0.8f); "comment">// Adjust size as needed
18 }
19 }
20}

Step 2: Configure Sprite Settings

Proper sprite configuration is crucial for good-looking animations:

Recommended Sprite Import Settings:

  • Texture Type: Sprite (2D and UI)
  • Sprite Mode: Multiple (for sprite sheets) or Single (for individual sprites)
  • Pixels Per Unit: Match your game's scale (typically 16, 32, or 64)
  • Filter Mode: Point (for pixel art) or Bilinear (for smooth art)
  • Compression: None or High Quality for best results
  • Pivot: Bottom for characters (feet on ground)

Step 3: Tag and Layer Setup

Organize your character for easy identification:

  • Set appropriate Tag (e.g., "Player", "Enemy", "NPC")
  • Assign to proper Layer (e.g., "Characters", "Entities")
  • Set Sorting Layer for proper rendering order

Sprite Preparation

Sprite Sheet Organization

Well-organized sprite sheets make animation setup much easier:

Recommended Sprite Sheet Layout:

Row 1: Idle_Down,    Idle_Down,    Idle_Down,    Idle_Down
Row 2: Idle_Up,      Idle_Up,      Idle_Up,      Idle_Up  
Row 3: Idle_Left,    Idle_Left,    Idle_Left,    Idle_Left
Row 4: Idle_Right,   Idle_Right,   Idle_Right,   Idle_Right
Row 5: Walk_Down,    Walk_Down,    Walk_Down,    Walk_Down
Row 6: Walk_Up,      Walk_Up,      Walk_Up,      Walk_Up
Row 7: Walk_Left,    Walk_Left,    Walk_Left,    Walk_Left
Row 8: Walk_Right,   Walk_Right,   Walk_Right,   Walk_Right
                        

Sprite Creation Tips:

  • Consistent Frame Size: All frames should be the same dimensions
  • Proper Spacing: Consistent spacing between frames if using padding
  • Direction Consistency: Characters should face the correct direction
  • Animation Timing: Consider the intended playback speed when creating frames
  • Loop Considerations: First and last frames should connect smoothly for looping animations

Individual Sprite Workflow

If you prefer working with individual sprite files:

Recommended Naming Convention:

Character_AnimationType_Direction_Frame
Examples:
- Hero_Idle_Down_01.png
- Hero_Idle_Down_02.png
- Hero_Walk_Left_01.png
- Hero_Walk_Left_02.png
- Hero_Attack_Up_01.png
                    

Using the Animation Editor

Step 1: Open the Animation Editor

Access the Character 2D Animation Editor through the Unity menu:

  1. Go to RPG Tools → Character 2D Animation Editor
  2. The editor window will open with all the necessary tools
  3. Dock the window wherever convenient in your workspace
Pro Tip: The Animation Editor remembers your settings, so you can close and reopen it without losing progress.

Step 2: Character Selection

Configure your character in the editor:

  1. Character Prefab: Drag your character GameObject into the field
  2. Direction Type: Choose from:
    • Four Directional: Down, Up, Left, Right
    • Eight Directional: Adds diagonal directions
    • Single Direction: For side-scrolling characters

4-Directional

Best for: Top-down RPGs, simple movement


Up

Left

Right

Down

8-Directional

Best for: Isometric games, smooth movement


Up-Left

Up

Up-Right

Left

Right

Down-Left

Down

Down-Right

Sprite Import Methods

Method 1: Individual Sprite Import

Import sprites one by one for maximum control:

  1. Select the Animation Type (Idle, Walk, Run, etc.)
  2. Choose the Direction
  3. Drag sprites into the frame slots
  4. Use "Add Frame" to add more slots
  5. Use "Remove" to delete unwanted frames

Individual Import Tips:

  • Sprites are automatically sorted by name when imported
  • You can reorder frames by dragging them
  • Empty frames will be skipped during animation creation
  • Each direction needs to be set up separately

Method 2: Sprite Sheet Extraction

Extract frames automatically from sprite sheets:

  1. Drag your sprite sheet into the Sprite Sheet field
  2. Configure the extraction settings:
    • Frame Size: Width and height of each frame
    • Start Frame: Which frame to start from (0-based)
    • Frame Count: How many frames to extract
    • Frames Per Row: How many frames are in each row
  3. Select the target Animation Type and Direction
  4. Click "Extract Frames from Sprite Sheet"
1"comment">// Example sprite sheet configuration "keyword">for a 32x32 character:
2"comment">// Frame Size: Width=32, Height=32
3"comment">// For a 4-frame walk cycle starting at frame 8:
4"comment">// Start Frame: 8
5"comment">// Frame Count: 4
6"comment">// Frames Per Row: 4 ("keyword">if your sheet has 4 frames per row)
7
8"comment">// This will extract frames 8, 9, 10, 11 from the sprite sheet
9"comment">// and assign them to the selected animation and direction

Sprite Sheet Extraction Example:

0
1
2
3
4
5
6
7
8
9
10
11

Selected frames (8-11) will be extracted for the current animation/direction

Animation Configuration

Speed and Loop Settings

Fine-tune your animations for the perfect feel:

Animation Type Recommended Speed Loop Setting Notes
Idle 0.3 - 0.5 Loop Slow, subtle movement
Walk 0.6 - 1.0 Loop Moderate speed for natural walking
Run 1.0 - 1.5 Loop Faster than walk, energetic
Jump 1.0 - 1.2 No Loop Quick, snappy action
Attack 1.2 - 2.0 No Loop Fast, impactful action

Custom Animation Types

Create custom animations for specific needs:

  1. Select "Custom" from the Animation Type dropdown
  2. Enter a name for your custom animation (e.g., "Spellcast", "Death", "Victory")
  3. Configure sprites and settings as normal
  4. The custom animation will be included in the generated animator controller

Custom Animation Examples:

  • Spellcast: Character casting magic spells
  • Death: Character falling or dying
  • Victory: Character celebrating success
  • Interact: Character interacting with objects
  • Crouch: Character crouching or hiding

Preview & Testing

Real-Time Animation Preview

The Animation Editor includes a built-in preview system:

Preview Controls:

  • Play/Pause: Start or stop animation playback
  • Next Frame: Advance to the next frame manually
  • Previous Frame: Go back to the previous frame
  • Animation/Direction Selection: Choose what to preview
🚶
Frame 1/4

Testing Best Practices

Ensure your animations look great:

Animation Testing Checklist:

  • □ All directions have consistent frame counts
  • □ Animation speeds feel natural and responsive
  • □ Looping animations connect smoothly
  • □ Character faces the correct direction
  • □ Sprite pivot points are consistent
  • □ No flickering or visual artifacts
  • □ Timing matches intended game feel

Animator Controller Generation

Export Configuration

Set up the export settings before generating your animator:

  1. Save Path: Choose where to save animation files (default: Assets/Animations)
  2. Controller Name: Name for your animator controller (e.g., "PlayerAnimator")
  3. Click "Create & Assign Everything" for a complete setup

Generated Animator Structure

The tool creates a sophisticated animator controller with:

Animator Components:

  • Parameters:
    • Horizontal (Float) - Current horizontal input
    • Vertical (Float) - Current vertical input
    • LastHorizontal (Float) - Last movement direction X
    • LastVertical (Float) - Last movement direction Y
    • Speed (Float) - Current movement speed
    • IsMoving (Bool) - Whether character is moving
    • Attack (Trigger) - Trigger attack animations
  • States:
    • Idle (Blend Tree) - Directional idle animations
    • Movement (Blend Tree) - Directional walk/run animations
    • Attack States - Individual attack animations per direction
  • Transitions:
    • Smooth transitions between idle and movement
    • Proper attack state handling
    • Direction-based blend tree navigation

Blend Tree Configuration

The generated blend trees provide smooth directional animation:

Blend Tree Structure:

Up (0, 1)
Up-Right (0.7, 0.7)
Right (1, 0)
Down-Right (0.7, -0.7)
Down (0, -1)
Down-Left (-0.7, -0.7)
Left (-1, 0)
Up-Left (-0.7, 0.7)
Center (0, 0)

Script Integration

Basic Movement Controller

Integrate the generated animator with your movement scripts:

1"keyword">using UnityEngine;
2
3"keyword">public "keyword">class Character2DController : MonoBehaviour
4{
5 [Header("Movement")]
6 "keyword">public "keyword">float moveSpeed = 5f;
7
8 [Header("Components")]
9 "keyword">private Animator animator;
10 "keyword">private Rigidbody2D rb;
11
12 "comment">// Input values
13 "keyword">private Vector2 movement;
14 "keyword">private Vector2 lastMovement;
15
16 "keyword">void Start()
17 {
18 animator = GetComponent<Animator>();
19 rb = GetComponent<Rigidbody2D>();
20
21 "comment">// Initialize last movement to face down
22 lastMovement = Vector2.down;
23 UpdateAnimatorParameters();
24 }
25
26 "keyword">void Update()
27 {
28 "comment">// Get input
29 movement.x = Input.GetAxis("Horizontal");
30 movement.y = Input.GetAxis("Vertical");
31
32 "comment">// Update last movement direction when moving
33 "keyword">if (movement.magnitude > 0.1f)
34 {
35 lastMovement = movement.normalized;
36 }
37
38 "comment">// Update animator parameters
39 UpdateAnimatorParameters();
40 }
41
42 "keyword">void FixedUpdate()
43 {
44 "comment">// Apply movement
45 rb.velocity = movement * moveSpeed;
46 }
47
48 "keyword">void UpdateAnimatorParameters()
49 {
50 "comment">// Current movement
51 animator.SetFloat("Horizontal", movement.x);
52 animator.SetFloat("Vertical", movement.y);
53
54 "comment">// Last movement direction ("keyword">for idle facing)
55 animator.SetFloat("LastHorizontal", lastMovement.x);
56 animator.SetFloat("LastVertical", lastMovement.y);
57
58 "comment">// Movement speed and state
59 "keyword">float speed = movement.magnitude;
60 animator.SetFloat("Speed", speed);
61 animator.SetBool("IsMoving", speed > 0.1f);
62 }
63
64 "comment">// Call "keyword">this method to trigger attack animation
65 "keyword">public "keyword">void Attack()
66 {
67 animator.SetTrigger("Attack");
68 }
69}

Advanced Features

Add more sophisticated behavior to your character:

1"keyword">public "keyword">class AdvancedCharacterController : MonoBehaviour
2{
3 [Header("Animation")]
4 "keyword">public "keyword">float walkSpeed = 3f;
5 "keyword">public "keyword">float runSpeed = 6f;
6 "keyword">public "keyword">bool canRun = true;
7
8 "keyword">private Animator animator;
9 "keyword">private "keyword">bool isRunning;
10
11 "keyword">void Update()
12 {
13 HandleInput();
14 UpdateAnimations();
15 }
16
17 "keyword">void HandleInput()
18 {
19 "comment">// Basic movement
20 movement.x = Input.GetAxis("Horizontal");
21 movement.y = Input.GetAxis("Vertical");
22
23 "comment">// Run input
24 isRunning = canRun && Input.GetKey(KeyCode.LeftShift);
25
26 "comment">// Attack input
27 "keyword">if (Input.GetKeyDown(KeyCode.Space))
28 {
29 Attack();
30 }
31
32 "comment">// Custom animation triggers
33 "keyword">if (Input.GetKeyDown(KeyCode.E))
34 {
35 TriggerCustomAnimation("Interact");
36 }
37 }
38
39 "keyword">void UpdateAnimations()
40 {
41 "comment">// Determine current speed
42 "keyword">float currentSpeed = isRunning ? runSpeed : walkSpeed;
43 Vector2 velocity = movement * currentSpeed;
44
45 "comment">// Update animator with appropriate values
46 animator.SetFloat("Horizontal", movement.x);
47 animator.SetFloat("Vertical", movement.y);
48 animator.SetFloat("Speed", velocity.magnitude);
49 animator.SetBool("IsMoving", velocity.magnitude > 0.1f);
50 animator.SetBool("IsRunning", isRunning && velocity.magnitude > 0.1f);
51
52 "comment">// Update last movement direction
53 "keyword">if (movement.magnitude > 0.1f)
54 {
55 animator.SetFloat("LastHorizontal", movement.x);
56 animator.SetFloat("LastVertical", movement.y);
57 }
58 }
59
60 "keyword">public "keyword">void TriggerCustomAnimation("keyword">string animationName)
61 {
62 animator.SetTrigger(animationName);
63 }
64
65 "comment">// Animation Events - called from animation clips
66 "keyword">public "keyword">void OnAttackComplete()
67 {
68 "comment">// Attack animation finished
69 Debug.Log("Attack complete
70 }
71
72 ">public ">void OnFootstep()
73 {
74 ">// Play footstep sound
75 AudioManager.Instance?.PlaySFX("Footstep");
76 }
77}

Animation Events

Add animation events for precise timing of actions:

1"keyword">public "keyword">class AnimationEventHandler : MonoBehaviour
2{
3 [Header("Audio")]
4 "keyword">public AudioClip[] footstepSounds;
5 "keyword">public AudioClip attackSound;
6
7 [Header("Effects")]
8 "keyword">public GameObject attackEffect;
9 "keyword">public Transform effectSpawnPoint;
10
11 "keyword">private AudioSource audioSource;
12
13 "keyword">void Start()
14 {
15 audioSource = GetComponent<AudioSource>();
16 }
17
18 "comment">// Called by animation event in footstep frames
19 "keyword">public "keyword">void OnFootstep()
20 {
21 "keyword">if (footstepSounds.Length > 0)
22 {
23 AudioClip clip = footstepSounds[Random.Range(0, footstepSounds.Length)];
24 audioSource.PlayOneShot(clip);
25 }
26
27 "comment">// Create dust effect at feet
28 CreateFootstepEffect();
29 }
30
31 "comment">// Called at the moment of attack impact
32 "keyword">public "keyword">void OnAttackImpact()
33 {
34 "comment">// Play attack sound
35 "keyword">if (attackSound != null)
36 {
37 audioSource.PlayOneShot(attackSound);
38 }
39
40 "comment">// Spawn attack effect
41 "keyword">if (attackEffect != null && effectSpawnPoint != null)
42 {
43 GameObject effect = Instantiate(attackEffect, effectSpawnPoint.position, effectSpawnPoint.rotation);
44 Destroy(effect, 2f); "comment">// Clean up after 2 seconds
45 }
46
47 "comment">// Check "keyword">for enemies in attack range
48 CheckAttackHit();
49 }
50
51 "comment">// Called when attack animation completes
52 "keyword">public "keyword">void OnAttackComplete()
53 {
54 "comment">// Re-enable movement or other systems
55 GetComponent<Character2DController>().enabled = true;
56 }
57
58 "keyword">void CreateFootstepEffect()
59 {
60 "comment">// Example: Create small dust cloud at character feet
61 Vector3 feetPosition = transform.position + Vector3.down * 0.5f;
62 "comment">// ParticleSystem or simple effect instantiation
63 }
64
65 "keyword">void CheckAttackHit()
66 {
67 "comment">// Simple attack range check
68 Collider2D[] hitEnemies = Physics2D.OverlapCircleAll(
69 effectSpawnPoint.position,
70 1f,
71 LayerMask.GetMask("Enemies")
72 );
73
74 "keyword">foreach (Collider2D enemy in hitEnemies)
75 {
76 "comment">// Apply damage or effects to enemy
77 enemy.GetComponent<Enemy>()?.TakeDamage(25);
78 }
79 }
80}

State Machine Behaviors

Create custom state machine behaviors for advanced animation control:

1"keyword">using UnityEngine;
2
3"comment">// Custom StateMachineBehaviour "keyword">for attack states
4"keyword">public "keyword">class AttackStateBehaviour : StateMachineBehaviour
5{
6 [Header("Attack Settings")]
7 "keyword">public "keyword">bool disableMovementDuringAttack = true;
8 "keyword">public "keyword">float attackDamage = 25f;
9 "keyword">public "keyword">float attackRange = 1.5f;
10
11 "keyword">private Character2DController controller;
12
13 "keyword">override "keyword">public "keyword">void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, "keyword">int layerIndex)
14 {
15 "comment">// Get controller reference
16 controller = animator.GetComponent<Character2DController>();
17
18 "comment">// Disable movement during attack
19 "keyword">if (disableMovementDuringAttack && controller != null)
20 {
21 controller.enabled = false;
22 }
23
24 "comment">// Face the last movement direction
25 Vector2 lastMovement = "keyword">new Vector2(
26 animator.GetFloat("LastHorizontal"),
27 animator.GetFloat("LastVertical")
28 );
29
30 "comment">// Additional attack setup logic
31 Debug.Log($"Starting attack in direction: {lastMovement}");
32 }
33
34 "keyword">override "keyword">public "keyword">void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, "keyword">int layerIndex)
35 {
36 "comment">// Attack state update logic
37 "comment">// Could check "keyword">for input cancellation, combo attacks, etc.
38 }
39
40 "keyword">override "keyword">public "keyword">void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, "keyword">int layerIndex)
41 {
42 "comment">// Re-enable movement
43 "keyword">if (controller != null)
44 {
45 controller.enabled = true;
46 }
47
48 "comment">// Reset any attack-specific states
49 Debug.Log("Attack completed");
50 }
51}
52
53"comment">// Custom behaviour "keyword">for movement states
54"keyword">public "keyword">class MovementStateBehaviour : StateMachineBehaviour
55{
56 [Header("Movement Effects")]
57 "keyword">public "keyword">float footstepInterval = 0.5f;
58
59 "keyword">private "keyword">float footstepTimer;
60
61 "keyword">override "keyword">public "keyword">void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, "keyword">int layerIndex)
62 {
63 footstepTimer = 0f;
64 }
65
66 "keyword">override "keyword">public "keyword">void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, "keyword">int layerIndex)
67 {
68 "comment">// Handle footstep timing
69 "keyword">float speed = animator.GetFloat("Speed");
70
71 "keyword">if (speed > 0.1f)
72 {
73 footstepTimer += Time.deltaTime;
74
75 "keyword">if (footstepTimer >= footstepInterval)
76 {
77 "comment">// Trigger footstep event
78 var eventHandler = animator.GetComponent<AnimationEventHandler>();
79 eventHandler?.OnFootstep();
80
81 footstepTimer = 0f;
82 }
83 }
84 }
85}

Troubleshooting Common Issues

❌ Animation Not Playing

✅ Solutions:

  • Check that Animator component has the controller assigned
  • Verify animation parameters are being set correctly
  • Ensure animation clips were created successfully
  • Check that sprite references in animation clips are not missing

❌ Character Facing Wrong Direction

✅ Solutions:

  • Verify sprite directions match your coordinate system
  • Check LastHorizontal/LastVertical parameter values
  • Ensure blend tree positions are set correctly
  • Test with manual parameter adjustment in Animator window

❌ Jerky or Stuttering Animation

✅ Solutions:

  • Adjust animation speed settings
  • Check transition duration settings
  • Ensure consistent frame timing
  • Verify sprite pivot points are consistent

❌ Missing Sprites in Animation

✅ Solutions:

  • Re-import sprite assets
  • Check sprite slice settings
  • Verify animation clip references
  • Recreate animation clips if necessary

Animation Best Practices

🎨 Sprite Quality

  • Use consistent frame sizes
  • Maintain pixel-perfect alignment
  • Keep pivot points consistent
  • Use appropriate compression settings

⚡ Performance

  • Optimize sprite atlases
  • Use appropriate texture sizes
  • Avoid excessive animation states
  • Pool particle effects

🎮 Game Feel

  • Match animation speed to gameplay
  • Add anticipation frames
  • Use proper easing curves
  • Test on target devices

🔧 Workflow

  • Name assets consistently
  • Organize sprites logically
  • Version control animation files
  • Document custom animations

Continue Learning

Explore related tutorials to expand your knowledge