- Home /
2D Collision Detection with Raycasting
I'm kind of stumped here.
I'm trying to set up movement controls for a basic top-down style game. Right now, I've got the following code to control player movement and collision detection with wall objects:
Vector3 vertSize = new Vector3(0f, 0.875f, 0f);
Vector3 horSize = new Vector3(0.5625f, 0f, 0f);
Vector3 vertSpeed = new Vector3(0f, 0.01f, 0f);
Vector3 horSpeed = new Vector3 (0.01f, 0f, 0f);
void Update ()
{
Vector3 spot = transform.position;
RaycastHit2D hit1;
RaycastHit2D hit2;
if (Input.GetKey ("s")||Input.GetKey ("down"))
{
hit1 = Physics2D.Raycast ((spot+(horSize/2)),-Vector2.up,((vertSize[1]/2)-vertSpeed[1]));
hit2 = Physics2D.Raycast ((spot-(horSize/2)),-Vector2.up,((vertSize[1]/2)-vertSpeed[1]));
if ((!hit1 && !hit2) || ((!hit1 && (hit2.collider.tag != "block"))) || (!hit2 && (hit1.collider.tag != "block")))
{
transform.Translate (-vertSpeed);
}
}
if (Input.GetKey ("w")||Input.GetKey ("up"))
{
hit1 = Physics2D.Raycast ((spot+(horSize/2)),Vector2.up,((vertSize[1]/2)+vertSpeed[1]));
hit2 = Physics2D.Raycast ((spot-(horSize/2)),Vector2.up,((vertSize[1]/2)+vertSpeed[1]));
if ((!hit1 && !hit2) || ((!hit1 && (hit2.collider.tag != "block"))) || (!hit2 && (hit1.collider.tag != "block")))
{
transform.Translate (vertSpeed);
}
}
if (Input.GetKey ("a")||Input.GetKey ("left"))
{
hit1 = Physics2D.Raycast ((spot+(vertSize/2)),-Vector2.right,((horSize[0]/2)-horSpeed[0]));
hit2 = Physics2D.Raycast ((spot-(vertSize/2)),-Vector2.right,((horSize[0]/2)-horSpeed[0]));
if ((!hit1 && !hit2) || ((!hit1 && (hit2.collider.tag != "block"))) || (!hit2 && (hit1.collider.tag != "block")))
{
transform.Translate (-horSpeed);
}
}
if (Input.GetKey ("d")||Input.GetKey ("right"))
{
hit1 = Physics2D.Raycast ((spot+(vertSize/2)),Vector2.right,((horSize[0]/2)+horSpeed[0]));
hit2 = Physics2D.Raycast ((spot-(vertSize/2)),Vector2.right,((horSize[0]/2)+horSpeed[0]));
if ((!hit1 && !hit2) || ((!hit1 && (hit2.collider.tag != "block"))) || (!hit2 && (hit1.collider.tag != "block")))
{
transform.Translate (horSpeed);
}
}
}
}
(there's almost certainly a cleaner/more elegant way to write this code, but for the moment I'm just concerned with making it work)
The idea here is that when a direction key is pressed, the player character object casts two rays, one on either of its sides, with a length equal to half of its size plus the distance the object can travel in a single frame. If neither of the rays hit any object, or if the object(s) that they hit do not have a "block" tag, then the player character is allowed to move in that direction this frame.
To test this, I have the player character in a game world with a single square object with the "block" tag. The script works just fine if I approach the square from the bottom or from the left. If I approach it from the top or from the right, however, the character just SLIGHTLY overlaps the block before stopping, which in addition to being wrong visually makes it so that the character can't move tangent to the surface of the block. If I "walk" onto the top of the block, for instance, then the bottom of the sprite overlaps the block slightly. From there, if I try to move left or right, the lower raycast will detect the block, and the character is unable to move.
The part I'm not getting is why this only happens when I approach the block from the top or from the right, and not when I approach the block from any direction. the script for walking left is identical to the script for walking right; the only difference is a few negative signs. At least if I was running into this problem regardless of which direction I approached the block from I could assume that there was an error in my script, but the same exact code works perfectly in one context but screws up in another. I have no idea why that is.
Not that it's related, but you need to use Time.deltaTime in order to prevent your movement from being framerate-dependent.
Answer by Aelrift · May 14, 2017 at 04:46 PM
You just need to use a collider for your player and every object it collides with and then make it so that wahenever it hits one it adds negative speed ( say if your player is going at 2 then when he hits a wall you'd add -2 speed so it would stop him from moving)
Your answer
![](https://koobas.hobune.stream/wayback/20220613125731im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Scale object, collision not working 2 Answers
How can I drag and drop 2D objects with the mouse without passing through other objects. 1 Answer
How do I properly handle a collision between a ball and a rectangle in 2D? 3 Answers
Health Bar Doesn't Go Down When Colliding With Enemy 2 Answers
Infinite Runner Live Training 2d collisions not working 2 Answers