web analytics

Collision Detection using Raycast

Today we are going to learn Collision Detection without using Collider Functions or the Rigidbody. Instead we are going to learn about RayCastHit and setup a Raycast Controller for detecting collisions.

The reason we are not using Rigidbody for collision detection is that the Raycast Controller handles slopes and moving platforms far more consistently over the Rigidbody, and also give far more greater fine tune control over the player movement.

What is a RayCast?

Raycast is a function of the Physics (Physics2D if we are working with a 2D project), that casts a ray against colliders in the scene.

62210330-compressed

A raycast is conceptually like a laser beam that is fired from a point in space along a particular direction. Any object making contact with the beam can be detected and reported.

In this example we are going to take examples of 2D objects to demonstrate collisions.

Physics2D.Raycast() function returns a RaycastHit object with a reference to the collider that is hit by the ray (the collider property of the result will be NULL if nothing was hit).

The layerMask (a layermask is a struct in Unity Engine, and is used to selectively filter game objects based on certain set property, such as a “tag” when casting rays)

rocket_mouse_unity_p3_36-compressed

It can be used to detect objects selectively only on certain layers which allows you to apply the detection only to enemy characters, or the ground and walls in this example.

Raycasts are also useful for determining lines of sight, targets hit by gunfire and for many other purposes in gameplay.

Image: Red Color Rays emanating from our blue Player GameObject to detect vertical collisions.

 

csa-compressed

As you can see that the rays are not actually being fired from the exact edge of the player’s bounds, but from a small width inside of them, which we are going to refer to as the skin width, and the reason for this is when the player is resting flush on the ground, we still have a small amount of space within which we can still effectively fire the rays.

Variables we will use and their functions :

In case of vertical collisions we, start emanating rays from our object, starting from the bottom Left corner. If the Ray hits an obstacle we know there is collision below the object and we set the velocity to Zero i.e. our play is still on top of an obstacle. Below, we have the function that will detect Vertical Collisions.

void VerticalCollisions(ref Vector3 velocity) { // 1. 
    float directionY = Mathf.Sign (velocity.y); // 2. 
    float rayLength = Mathf.Abs (velocity.y) + skinWidth; //3. 
    
    for (int i = 0; i < verticalRayCount; i ++) { //4. 
      Vector2 rayOrigin = (directionY == -1)? raycastOrigins.bottomLeft:raycastOrigins.topLeft; //5. 
      rayOrigin += Vector2.right * (verticalRaySpacing * i + velocity.x); // 6. 
      RaycastHit2D hit = Physics2D.Raycast(rayOrigin, Vector2.up * directionY, rayLength, collisionMask); // 7. 
      
      Debug.DrawRay(rayOrigin, Vector2.up * directionY * rayLength,Color.red); //8. 
      
      if (hit) { //9. 
        velocity.y = (hit.distance - skinWidth) * directionY; //10.
        rayLength = hit.distance;
      }
    }
  }

 

1.  We have taken an argument Velocity which is passed as a Reference (passing an argument as reference means that whatever changes are made to that variable in the function in which it is used, will directly reflect to the variable passed)

2.  directionY is float variable which will store the Sign of y component of velocity, which mean if our Player is moving down then the value will be -1 and we have to Raycast below our Player and detect collisions below our Player.

3. float rayLength will simply store the length of the ray from our Player Object to the nearest Obstacle.

4. For loop which will start from the left most ray till the right most ray and will check collisions in each case

5. Here, we want to see in which direction we are moving, so if we are moving down we want our rays to start from the bottom left corner, or if we are moving up we want our rays to start from topLeft corner.

6. Here we want to add to rayOrigin, since we want to cast our rays from the point where we will be once we have actually moved on the x-axis;

7. Now we create a new RaycastHit2D variable so we will perform a Raycast from our rayOrigin, we then want it to go to direction Y so we have Vector2.up * directionY, for the distance we have rayLength, and then the Layermask variable collisionMask which we have to set in Inspector to determine which object we want to collide with, which will be Obstacles.

8. Debug.DrawRay is not detecting any collsions. It is simply for us to see the development phase where the Rays are starting from and where they are ending at.

9. If our Raycast hits something, then hit well be true and we can set the velocity accordingly. Here we want to set our Y velocity equal to the amount that we have to move to get from our current position to the point at which the ray intersected with an Obstacle (the ray distance).

10. We set our Y velocity by using hit.distance to get the distance, and multiply by directionY to maintain the direction. (we subtract skin width since we added it above in the rayLength variable in point 3.

We can similarly make our Horizontal Collisions function to detect collision with walls, etc.

coll-compressed

Click Here to download the UnityPackage file which which has a basic functioning Player with working Collision detection using RayCasts.

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *