2D Top Down Movement (Up, Down, Left, Right, aka RPG Style)

Getting Set up

Make sure that you have enabled the Input System (Window > Package Manager) then search for Input System

Create a 2D Level with some object on it.

The example below is a black square background with multiple 2D Sprites added that are set to be white.

Each Sprite (except the background) has a collider attached to it. This is either a Polygon Collider 2D, Circle Collider 2D, Box Collider 2D or a Capsule Collider 2D in this example.

The camera has been zoomed back and the projection set to Orthographic.

Adding the Player

Add your player image into the assets folder.

Select the image and go to the Inspector.

Change the Texture Type to Sprite 2D and UI

Click Apply

You now have a sprite to use as the player.

Create an empty GameObject on the scene and rename it Player. This will act as a container for the player objects.

Now drag the player sprite onto the player object

Resize and reposition the player object if needed

Add a Box Collider 2D object to the player.

Resize it if needed.

Add a Player Input component to the Player object.

Either create a default set of actions or use one you have previously created.

Add a Rigidbody 2D component to the player. Set Gravity Scale to 0.

Create a new script, in this case PlayerMovement2D_TopDown_UDLR.

Attach the script to the Player.

Open the script.

We need to add the Input System so that we can detect the player pressing inputs which will then update the position of the players rigid body component.

Line 4 imports the Input System.

Lines 9-11 create the variables that are used to handle player movement.

  • Rigidbody2D rb creates a variable to store the rigidbody component that is on the player object.
  • Vector2 movement create a 2D vector for storing the user input on the x and y axis. left is -1, right is 1 on the x axis, up is 1 and down is -1 on the y axis. 0 is centred. This allows for the simulation of a d-pad (directional pad)
  • We also have a public float to store the speed of the player. This exists to make it easier to update the speed of the player dynamically.

In the Start() method on line 17 we assign the existing player object rigidbody to the variable created earlier.

Lines 15-18 involve creating the OnMove method (note Move is the name of the input in the InputActions asset, we can access any action by putting On infront of it and creating a method). This take an InputValue parameter. This InputValue stored details about what input has been pressed.

We know that it is a Vector2 so we use the built in Get method to get a Vector2 from the InputValue with the code iv.Get<Vector2>() this is then assigned to the movement variable created on line 10.

Finally in the Update() method we move the player with the code on line 27. The Rigidbody has a built in method MovePoisition that takes a vector and moves the player object to that position. We get the current position of the object with rb.position we then add the new position with + movement * playerSpeed * Time.deltaTime with this we can consistently move the player in relation to the time. as movement contains values for x and y between -1 and 1 it will move them in that direction.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;

public class PlayerMovement2D_TopDown_UDLR : MonoBehaviour
    // Object Variables
    Rigidbody2D rb;
    Vector2 movement;
    public float playerSpeed = 5;

    // Start is called before the first frame update
    void Start()
        rb = GetComponent<Rigidbody2D>();

    void OnMove(InputValue iv) {
        movement = iv.Get<Vector2>();

    // Update is called once per frame
    void Update()
        rb.MovePosition(rb.position + movement * playerSpeed * Time.deltaTime);

Test your project.

You will find that when your player collides / hits an object the object rotates.

To fix this open up the Rigidbody of the player and select Freeze Rotation Z

The next guide will show how to apply different animations to the player depending on what button is being pressed.