Top-Down 2D Game Collision

I’m working on my first Top-Down 2D game. So far all I’ve got is a basic player movement system, but it’s giving me issues. I need to create a system so that the player can collide with walls, but considering it’s my first time attempting this I can’t think of a way to do this.

For reference, this is the movement script.

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

public class PlayerMovement : MonoBehaviour
{
    [SerializeField] public float playerSpeed;

    //I thought using a LayerMask might help, although I'm not sure how to utilize it.
    public LayerMask walls;

    void Update()
    {
        if (Input.GetKey(KeyCode.W))
        {
            transform.position = new Vector3(transform.position.x, transform.position.y + playerSpeed, transform.position.z);
        }
        if (Input.GetKey(KeyCode.A))
        {
            transform.position = new Vector3(transform.position.x - playerSpeed, transform.position.y, transform.position.z);
        }
        if (Input.GetKey(KeyCode.S))
        {
            transform.position = new Vector3(transform.position.x, transform.position.y - playerSpeed, transform.position.z);
        }
        if (Input.GetKey(KeyCode.D))
        {
            transform.position = new Vector3(transform.position.x + playerSpeed, transform.position.y, transform.position.z);
        }
    }
}

I’m sorry if this seems trivial, I’m quite new to Unity and I’m not familiar with the standard stuff yet.

You are doing the physics above.

Instead check out some tutorials on how to move stuff with Physics2D (with Rigidbody2D).

This will let you trivially put colliders on the player and walls.

The above code must change when you go to physics.

With Physics (or Physics2D), never manipulate the Transform directly. If you manipulate the Transform directly, you are bypassing the physics system and you can reasonably expect glitching and missed collisions and other physics mayhem.

Always use the .MovePosition() and .MoveRotation() methods on the Rigidbody (or Rigidbody2D) instance in order to move or rotate things. Doing this keeps the physics system informed about what is going on.

With a wheel collider, use the motor or brake torque to effect motion.

Okay, I’ve edited the code to work with MovePosition. I’m able to get it to move around, but it still isn’t colliding with anything. Am I doing something wrong?

For the record, the character and all the walls have box colliders and kinematic rigidbody components.

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

public class PlayerMovement : MonoBehaviour
{
    [SerializeField] public float movementSpeed;
    public Vector2 playerSpeed;

    public Rigidbody2D rb2d;

    private void Start()
    {
        rb2d = GetComponent<Rigidbody2D>();
    }

    private void Update()
    {
        if (Input.GetKey(KeyCode.W))
        {
            playerVelocity = new Vector2(playerVelocity.x, movementSpeed);
        }
        else if (Input.GetKey(KeyCode.S))
        {
            playerVelocity = new Vector2(playerVelocity.x, -movementSpeed);
        }
        else
        {
            playerVelocity = new Vector2(playerVelocity.x, 0);
        }
        if (Input.GetKey(KeyCode.A))
        {
            playerVelocity = new Vector2(-movementSpeed, playerVelocity.y);
        }
        else if (Input.GetKey(KeyCode.D))
        {
            playerVelocity = new Vector2(movementSpeed, playerVelocity.y);
        }
        else
        {
            playerVelocity = new Vector2(0, playerVelocity.y);
        }
    }

    void FixedUpdate()
    {
        rb2d.MovePosition(rb2d.position + playerVelocity * Time.deltaTime);

        Debug.Log(transform.position);
    }
}

Kinematic is the problem. It’s counter-intuitive. Kinematic means it’s just there to detect collisions, not to move anything. So it will happily penetrate colliders.

Steps:

  • Turn OFF Kinematic

Optional:

  • assign your playerVelocity to the Rigidbody velocity
  • Remove line 47: that will let the physics system move it according to Rigidbody velocity.

Otherwise you should be able to just keep moving it

It worked! Thanks a bunch.

The only reason I ever set it to kinematic was that the tutorial claimed MovePosition was best suited for kinematic. It was a bit misleading.

But anyway, it works now. Have a good day!

1 Like