Creating a Player and Tilemap

Let’s see how well you remember creating GameObjects in a Scene from the Platformer. If you need to review, visit the Platformer’s Creating a Player and Creating a Tilemap tutorials again.

Tilemap

When creating the tilemap, be sure to add a Tilemap Collider 2D and a Composite Collider 2D. The Composite Collider will make it so that collision is applied to the tilemap as a whole instead of each tile individually, improving performance.

Composite Collider

To ensure that the tilemap remains in place, be sure that you change these properties on the Rigidbody 2D that was added with the Composite Collider.

  1. Body Type Kinematic
  2. Collision Detection Continuous.

Composite Collider

Player

Add a Player GameObject to the Scene. I used a Circle for mine with a Circle Collider 2D and Rigidbody 2D. Be sure to tag the Player as a Player tag and to add the Main Camera as a child of the player.

Player Camera Child

Player Tag

Top-Down Player Controller Script

Update() vs. FixedUpdate()

This time (as opposed to our script in our platformer), we won’t be moving by adding forces to the Player’s Rigidbody in FixedUpdate(). Instead, we will directly mutate the position of the transform component, which can be done in Update(). Rigidbody code MUST go in FixedUpdate() while everything else can go in Update().

using UnityEngine;

public class TopDownController : MonoBehaviour
{
    public float speed;
    public float maxSpeed;
    Rigidbody2D rb;
    // Start is called before the first frame update
    void Start()
    {
        rb = GetComponent<Rigidbody2D>(); // this gets the player's rigidbody component so we can change it here in the code
    }

    // FixedUpdate is called once per frame
    void FixedUpdate()
    {
        // --- Calculate User Input ---
        // A Vector2 is like a coordinate point. It has 2 numbers inside, x and y
        // the first number (x) will be -1 for left button, +1 for right button, and 0 for neither/both
        // the second number (y) will be -1 for down button, +1 for up button, and 0 for neither/both
        // Example: Vector2(0, 1) = straight up
        // Example: Vector2(-1, 0) =  straight left
        // Example: Vector2(1, -1) = diagonal direction right and down
        Vector2 direction = new Vector2(
            Input.GetAxis("Horizontal"),
            Input.GetAxis("Vertical")
        ).normalized;

        // --- Move the Player ---
        // Add force in the direction the player is pressing the buttons
        // The amount of force is controlled by the "speed" variable we made
        rb.AddForce(direction * speed, ForceMode2D.Impulse);
        // --- Cap the maximum speed ---
        // Cap Right
        if (rb.linearVelocityX > maxSpeed) // English: if player speed X is greater than our max... (right is positive)
        {
            rb.linearVelocityX = maxSpeed; // English: then make it equal to the max instead
        }
        // Cap Left
        if (rb.linearVelocityX < -maxSpeed) // English: if player speed X is less than our NEGATIVE max... (left is negative)
        {
            rb.linearVelocityX = -maxSpeed; // English: then make it equal to the NEGATIVE max instead
        }
        // Cap Up
        if (rb.linearVelocityY > maxSpeed) // English: if player speed Y is greater than our max... (up is positive)
        {
            rb.linearVelocityY = maxSpeed; // English: then make it equal to the max instead
        }
        // Cap Down
        if (rb.linearVelocityY < -maxSpeed) // English: if player speed Y is less than our NEGATIVE max... (down is negative)
        {
            rb.linearVelocityY = -maxSpeed; // English: then make it equal to the NEGATIVE max instead
        }
        // --- Stop Player from Sliding ---
        // Stop moving if not pressing any buttons
        if (direction.x == 0) // if we aren't pressing left or right
        {
            rb.linearVelocityX = 0; // set speed to 0 (aka stop moving left or right)
        }
        if (direction.y == 0) // if we aren't pressing left or right
        {
            rb.linearVelocityY = 0; // set speed to 0 (aka stop moving up or down)
        }
    }
}

We have are dividing by SPEED_UNIT because if we moved by speed every frame (60x a second), we would go too far too quickly.

Set speed in the Inspector

I set my Speed to be 20 as well as the Gravity Scale of the Rigidbody to be 0 (because we do not have gravity in this game). Also, I set the collision of the Rigidbody to be Continuous.

Script speed

Draw some tiles and test out your game’s movement.