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.
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