Skip to content
ReadySpawn

How to make a 2D platformer character controller in Unity

By Imersa Studios · Updated

Move a Rigidbody2D horizontally, check the ground with an overlap circle, and add three feel features: variable jump height (release to jump lower), coyote time (jump just after leaving a ledge) and jump buffering (jump just before landing). The script below does all of it.

1. Set up the scene

  • Add a Rigidbody2D (Gravity Scale 3 to 4 feels snappy) and a collider to the player.
  • Add an empty child at the feet named GroundCheck.
  • Put ground colliders on a Ground layer.

2. The controller

using UnityEngine;

[RequireComponent(typeof(Rigidbody2D))]
public class PlatformerController : MonoBehaviour
{
    public float moveSpeed = 7f;
    public float jumpForce = 12f;
    public float coyoteTime = 0.1f;
    public float jumpBuffer = 0.1f;
    public Transform groundCheck;
    public float groundRadius = 0.15f;
    public LayerMask groundMask;

    Rigidbody2D rb;
    float coyoteCounter, bufferCounter, input;

    void Awake() => rb = GetComponent<Rigidbody2D>();

    void Update()
    {
        input = Input.GetAxisRaw("Horizontal");
        bool grounded = Physics2D.OverlapCircle(groundCheck.position, groundRadius, groundMask);

        coyoteCounter = grounded ? coyoteTime : coyoteCounter - Time.deltaTime;
        bufferCounter = Input.GetButtonDown("Jump") ? jumpBuffer : bufferCounter - Time.deltaTime;

        if (bufferCounter > 0f && coyoteCounter > 0f)
        {
            rb.linearVelocity = new Vector2(rb.linearVelocity.x, jumpForce);
            bufferCounter = 0f;
            coyoteCounter = 0f;
        }

        // Variable jump height: releasing early cuts the jump short.
        if (Input.GetButtonUp("Jump") && rb.linearVelocity.y > 0f)
            rb.linearVelocity = new Vector2(rb.linearVelocity.x, rb.linearVelocity.y * 0.5f);
    }

    void FixedUpdate() => rb.linearVelocity = new Vector2(input * moveSpeed, rb.linearVelocity.y);
}

This uses Unity 6's linearVelocity; in older versions use velocity. It reads the classic Input Manager; with the Input System package, read the same actions from your input asset.

3. Why the three feel features matter

FeatureWhat the player feels
Coyote timeJumps right after running off a ledge still work, so the game feels fair
Jump bufferA jump pressed just before landing still happens, so the game feels responsive
Variable heightTap for a small hop, hold for a high jump, giving control

4. Tune it

Make the jump a little too snappy first, then tone it down. Raise gravity scale for a heavier fall. Add a small fall gravity multiplier so descent is faster than ascent. Playtest with other people, because feel is subjective.

5. Next steps

Add a dash, wall slide and animations, then design a small map. How to make your own Hollow Knight is the roadmap, and how to animate a character in Blender covers rigs for 3D characters. For an art look, see Readable Pixels.

Questions

Who wrote this

Imersa Studios builds the Unity systems, low poly packs and field guides sold on itch.io. The code and techniques here come from shipping those products. More about the studio.