Monthly Archives: November 2016

Raycasting Part 1: Everybody Loves Raycasting

raycasting1

Raycasting is one of those topics that everyone seems to struggle with at first, so here is a tutorial covering everything you need to know about raycasting in Unity. In this post I’ll explain what a raycast is, how to use a simple raycast, and point out a few potential problems and pitfalls people run into when using raycasts. More uses of raycasts will be covered in separate posts. A small downloadable demo is included to get you started.

What is a raycast?

A raycast is an ‘imaginary line’ that you can ‘shoot’ through your game scene in order to detect what is in the way of that line (colliders specifically).

  • Raycasts can be either 3D or 2D (you need to use the correct type in order to detect your colliders, as 3D raycasts won’t detect 2D colliders and vice versa).
  • Raycasts can shoot as far as you like, and therefore can detect multiple colliders, or you can just detect the first object in the ray’s sights.
  • Raycasts can be set to use specific physics layers, so you can detect only objects you need to and ignore anything else.

Why would I use a raycast?

Raycasts can be used for all kinds of things, like:

  • Character line of sight (detecting if a character can ‘see’ something)
  • Determining where a missile hit something
  • An alternative to physics collision detection (a lot of platform games replace standard physics with raycasting solutions, which give more control)
  • Input (is an object under a mouse click or touch event).

How do I use a raycast?

It’s actually pretty easy to use a raycast, but it can be tricky to get it right if you’re not careful. We’ll work with 2D raycasts for this demo because it’s easier to demonstrate, but 3D raycasts work exactly the same way, just with an extra axis when determining the direction to shoot the invisible ray.

A raycast needs some parameters:

  • an origin from which the ray starts
  • a direction the ray will travel in
  • a distance for the ray to travel (optional – infinity by default)
  • a layermask to determine what objects (colliders) can and can’t be detected by the ray (optional – all layers by default).

Here’s the ‘looking’ code for the demo scene in the sample project you can download below:


void LookForFood()
{
    var hit = Physics2D.Raycast(eyeLine.position, Vector2.right, 5f, visibleObjects);
    if (hit && hit.transform.name == "Carrot")
    {
        // do something to indicate the rabbit sees a carrot
    }
}

In this simplified example, the rabbit is looking directly to his right and his sprite changes colour to green if he can see a carrot.

The line that does the raycasting is:

 var hit = Physics2D.Raycast(eyeLine.position, Vector2.right, 5f, visibleObjects);

This shoots a raycast from the position of the rabbit’s eyeline (eyeline.position), traveling in the direction of Vector2.right (directly to the right of the rabbit’s eyes). The raycast travels for a distance of 5 units (i.e. that’s how far the rabbit can ‘see’ – the raycast will not hit any colliders more than 5 units away from the rabbit’s eyes), and the last parameter is a layermask that determines which objects the rabbit can see.

The hit variable will store a RaycastHit2D with information about the collider it detected (it will be null if nothing is hit).

In this example the rabbit can see stone or carrots (the food and stone layers are set in the rabbit’s visibleObjects layermask), and only one object is detected by Physics2D.Raycast (you can detect more, but that will be covered in a separate article). Therefore, if a stone is in front of the carrot, the rabbit will only see the stone, but since the rabbit cannot see windows, he will see a carrot behind a window (as long as he’s close enough).

Download the demo project
Download the sample project to play around.
NOTE: To keep the demo simple, I’ve not included any controls. To test the functionality, start the demo, then switch to the Scene window and drag the rabbit object around with the mouse. Keep an eye on the rabbit’s colour to see when he spots a carrot.

 

Potential Pitfalls

Parameter Confusion

Because of the variable types used, if you put a layermask in Physics2D.Raycast as the third parameter, Unity will assume it’s the distance you want the raycast to shoot, so you will find your layermask not working! The easy solution is to always specify a distance as well.

Direction vs Target

Many people get confused when putting in the raycast direction. This needs to be the direction the ray shoots, not the destination it shoots towards. If, for example, you put the position of an enemy as the direction vector, the ray would not go towards that position and hit the enemy (unless it just happened to coincidentally be in the right place). Getting the right direction vector can stump beginners, so read up on basic vector maths if you are confused by it.

An example you might want to try is checking if any objects are between the player’s eyes and an enemy. To get this direction you would need to subtract the starting vector from the destination vector.

Debug Ray

As mentioned earlier, the raycast is invisible, so you can’t see it! Combine this with the tendency for beginners to have a hard time with vector mathematics and you have a potential for error.

Luckily, you can simulate your raycast in the Scene window using the following:

Debug.DrawRay(eyeLine.position, Vector2.right, Color.magenta, 0.1f);

This will draw a short line along the same path as your ray so you can make sure it is firing in the correct direction. The colour parameter determines the colour of the line, and the final parameter is how long you want the line to be visible in the Scene window for before it disappears.

Just make sure the first two parameters match your actual raycast exactly! A trick I use is to use a variable to hold a calculation rather than ‘hard coding’ the parameters. That way any change to the calculation will affect both the real ray and the debug ray without the risk of changing one but not the other.

LayerMask Confusion

Double-check your layermask if you use one. If you set your layermask in code, be sure you understand what you’re doing, as layermasks use a counter-intuitive way of setting the layers. You can see more information here.

Conclusion

That’s your introduction to raycasts! Download the demo if you want to try it out or try it out in your own project. If you have any problems, double-check everything in the potential pitfalls listed above.