Unity Cookbook. 2D animation

2D animation

Two ways to 2D character animation

  • Sprite sheet animation
    • Characters are drawn fully, and animated by hand, frame by frame
    • At best, results in lifelike and beautiful motion
    • At worst, the animator has to draw everything multiple times
    • Learn: Sprite Animation
  • Skeletal animation
    • Characters consists of multiple images connected by bones
    • At best, varied procedural movement out of a few assets
    • At worst, stiff and unlifelike motion
    • Learn: Skeletal Animation

Sprite-based animation

Creating a new animation

  • Manual: Creating a new Animation Clip
  • Select the GameObject you want to animate
  • Open Animation Window: Window > Animation > Animation
  • Click Create to create a new animation (.anim) file, or a clip
    • An animation controller (.controller) gets created simultaneously as well
    • Also, your GameObject gets an Animator component
    • Name the first clip PlayerIdle
    • Good ideas to have separate animation files for Idle, Jump, Run, etc…

  • Note: The functionality of the animation timeline above relies that you keep your GameObject selected
    • Otherwise, you can’t click the buttons
  • Drag sprites to your Animation timeline
    • Note: The final frame duration is less than the others. For an easy fix, add a new key to the end with Right click > Add key
  • Set Samples to a lower value to make your new animation less frantic
  • You can create new clips in the PlayerIdle dropdown

Controlling animation with code

  • The fastest way to get your animations running is to control the Animator component with code
  • Script Reference: Animator.Play
    Animator anim = GetComponent<Animator>();
    anim.Play("PlayerAttack");
    
  • Check which animation is playing
    if (anim.GetCurrentAnimatorStateInfo(0).IsName("PlayerAttack"))
    {
          Debug.Log("Playing attack anim!");
    }
    

Animator controller

Animator window

  • Unity Animator window, aka the Animation State Machine can seem daunting if you’re not familiar with the concept of a State Machine
  • Luckily, the Manual has good resources about state machines
  • Note: the animator window can be janky. E.g., If you cannot move the states around, set the inspector into Debug mode
    • Inspector window > Three dots in the top right corner > Debug

Using the Animator window

  • In Animator, we can create transition rules between animation clips
  • Right click a state > Make Transition
  • Entry is the default state: Create an arrow from it to the idle animation!
  • Click on the arrow to edit the transition

Transitions

bg right:35% height:95%

  • Has Exit time:
    • The most absolutely confusingly named variable of all years
    • Means: “Transition will happen automatically after Exit time has passed”
    • Usually we want to uncheck this.
  • Settings
    • Exit time: The number of loops to go through before the automatic transition
      • Oh wow, it’s not even time, really
    • Transition Duration: In sprite animations, we usually want to set this to 0.

Animation parameters

  • To trigger state transitions, we control the controller’s parameters in code
  • Manual: Animation Parameters
  • Change the Layers view to Parameters
  • Create a new float parameter named Speed
  • Go to a transition, and create a new condition for the parameter
    [SerializeField] Animator anim;
    
    anim.SetFloat("Speed",_rigidbody.velocity.Magnitude);
    
  • anim.SetTrigger("StartWalking") works similarly

Animation clip properties

  • We can control component properties straight from the animation clips themselves
  • Use case: If we want to use the same walk animation sprites for PlayerWalkLeft that we have for PlayerWalkRight
  • In the PlayerWalkLeft animation clip, click Add Property
    • Choose Sprite Renderer Component
    • Choose the FlipX property
    • Tick the box, and move the created key to the start of the clip

Blend trees

  • Having animation states for all moving directions can lead to “transition hell”
  • We can keep the base layer simpler by creating blend trees: Manual: Blend trees
  • A common usage for blend trees is to add directional animation:
    • E.g., a PlayerWalk blend tree that contains PlayerWalkDown, PlayerWalkUp, etc states
    • Create a blend tree by right-clicking the animator background and choose
      • Create state > From new blend tree
    • Name the blend tree to PlayerWalk, and double click the blend tree to open it
  • Note: You can also convert an existing state into a blend tree with Right click > Create blend tree from state

Creating a 2D blend tree

  • Change Blend type to 2D Simple directional.
  • Set two float parameters to control the blend tree (here: XSpeed and YSpeed)
    • Create the parameters if you need to.
  • Press + to add four empty Motion fields (a.k.a., slots for the animation clips) to the blend tree

Adding animation clips to a blend tree

  • Drag the animation clips from the Project view to motion fields
  • Set the Pos X and Pos Y parameters or drag the motion fields to their corresponding positions (PlayerWalkDown should be down, etc.)
    • Values of 0.1 seem to work well so the states are triggered even when the analog stick is moved slightly. See image in the previous slide!
  • Now, when you change the values of the parameters XSpeed and YSpeed, the blend tree will go to the motion field that matches the values the best

Animation controller example

displacement = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
displacement = Vector2.ClampMagnitude(displacement, 1);
rb.velocity = displacement * Time.deltaTime * walkSpeed;

animator.SetFloat("WalkSpeed", rb.velocity.magnitude);

if (displacement.magnitude > 0.1f)
{
    animator.SetFloat("XSpeed", displacement.x);
    animator.SetFloat("YSpeed", displacement.y);
}
  • Here, we set three properties:
  • WalkSpeed is used to transition between PlayerIdle and PlayerWalk blend trees
  • XSpeed and YSpeed are used to choose direction in the blend trees
    • Note that we don’t reset them when movement stops!

Controlling animation clip speed

bg right:30% height:50%

  • You can control the speed an animation clip is played easily by setting a parameter to control it
  • Click on a state in the animator to show it in the inspector
    • Check Parameter under Speed
    • Choose the float parameter you want to use as a multiplier for the animation clip speed
    • Done!

Extra: Animation Events

Extra: State machine behaviour scripts

Extra: UI animations

Extras

Extras: Pixel art in Unity

  • Sprite import:
    • Texture type: Sprite (2D and UI)
    • Pixels Per Unit: Tile size (e.g., 32)
    • Filter Mode: Point (No filter)
    • Compression: None
  • Edit > Project Settings > Quality > Anti-aliasing: Disabled

  • Preparing for pixelart
  • Pixel perfect camera
    • Packages: Pixel perfect camera
    • Many issues can be fixed by using a pixel perfect camera instead of a basic camera
    • For instance, you can crop the play area to represent a low resolution display
    • This can also be used for uniformly scaling the pixels by an integer amount
  • Note: If you still see black gaps in your tilemaps after following these instructions, create a new material with the Sprites/Default shader and check Pixel snap. Then, add this material to every Tilemap renderer.

Learning