How to make a basic 2D Top-Down Player Controller in Unity

Top down games are pretty popular today in the rpg genre but also in a lot of others. But there's not a ton of tutorials that clearly explains how to make one yourself. If you're a bit lost on how to make a 2d top down player controller in unity and don't know where to start, well I have good news. In this tutorial we will cover the basis of making your player move around in your map and animate it with sprites, while making a strong base code wise to continue after this your game project without getting an headache.

Getting started

Before we proceed, you will need to download the 2D assets we'll be using in this tutorial, or you can use your own and still follow along the different steps. You can download it here. It's from the 16x16 Dungeon TileSet 2 of 0x72 and the 2D Pixel Dungeon from Pixel_Poem. We'll only be using the Knight sprite from the first asset pack because the tileset is organized in a bizarre way and I am not a fan of the 2D Pixel Dungeon characters. Again feel free to use any asset from the original tilesets and/or your own.

Make a new 2D project in Unity and import your assets in the editor in a new folder Sprites. Don't forget to turn off the compression and the filter mode to Point (no filter) on the sprites import settings. You can also put the Pixel Per Unit value to 16.

Now select the dungeon tileset and change it's sprite mode from Single to Multiple (on the Inspector Menu). Go into the sprite editor click on the little arrow and chose Grid By Cell Size, and 16 to x and y, then slice. This will split your tileset to multiples tiles of 16 x 16 pixels.

We will repeat the same process for the knight tileset, except we will choose automatic as the type of splitting, because the size of the sprite vary and is not exactly 16 by 16.

For the pleasure of the eye,let's make a simple map by using a tilemap and our tiles.

Creating a simple map

Let's start by creating two tilemaps in our scene. This is done by right clicking on the Hierarchy tab of your editor, and in the menu 2D > TileMap. This will create a grid component with a tilemap as its child. We're making two different tilemaps because we want one for the walls, and one for the floor. This will allow us to do easy collision and some cool graphical effects. We will then create a tile palette to help us make a map easily. This is done by opening the Tile Palette window (Window > 2D > Tile Palette) and clicking the Create a new Tile Palette button. You can then just drag the dungeon tileset in the Tile Palette window and Unity will create it for you.

We can now paint a very simple level to let our little 2d player frolic freely. Be careful when making your map : you have one tilemap for the floor and one for the walls. If you can't see the walls because they are behind the floor tiles, go into the inspector of the floor tilemap and put it's order in layer to -1.

If you encounter a tearing problem (undesired padding between tiles) you can create a Sprite Atlas and reference your tileset in it. It will prevent this problem in runtime by making sure no oversampling in your tiles is seen.

Creating our Player Controller

Let's start by creating an empty GameObject and calling it Player. Drag and drop the first frame of the knight tileset in your Player GameObject. This will create a child with a sprite renderer component. Add a Rigidbody2D component to the Player game object, set its gravity scale to 0 and freeze the z rotation in the constraints. Create a new script PlayerController. You can begin to organize your scripts in a designated folder.

Let's open our script now.

using UnityEngine;


public class PlayerController : MonoBehaviour

{

private Rigidbody2D _rigidbody2D;

private Vector2 _movement;

[SerializeField] private float movementSpeed;


private void Awake()

{

_rigidbody2D = GetComponent<Rigidbody2D>();

}


private void Update()

{

_movement.x = Input.GetAxisRaw("Horizontal");

_movement.y = Input.GetAxisRaw("Vertical");

}


private void FixedUpdate()

{

_rigidbody2D.MovePosition(_rigidbody2D.position +

_movement.normalized *

(movementSpeed *Time.fixedDeltaTime));

}

}