Physics class in the Unity engine has many methods related to detecting collisions with other physical objects. One of such methods is Raycast, but do you know that you can also cast different shapes?
Let’s explore the world of physics casts and see know to use them!
Raycast ?
The most popular method would be Raycast method.
This method “shoots” the ray from the origin position in a given direction. We can limit this ray’s length if we want to, but by default, the length is infinite.
Code example:
using UnityEngine; /// <summary> /// Use example for Raycast method. /// </summary> public class RayExample : MonoBehaviour { /// <summary> /// Called each physics frame. /// </summary> private void FixedUpdate() { Ray ray = new Ray(transform.position, transform.forward); // Defines ray RaycastHit hitResult; // Stores the result // Call Raycast if (Physics.Raycast(ray, out hitResult)) { Debug.Log($"Raycast hitted: {hitResult.collider.name}"); } } }
Linecast ?
The Linecast method is really similar to the Raycast method.
The difference between those two is the definition. In Raycast, we are defining the start position and direction. In Linecast, we define the start and end position.
This method checks if there is something in between those two points.
Code example:
using UnityEngine; /// <summary> /// Use example for Linecast method. /// </summary> public class LineExample : MonoBehaviour { /// <summary> /// Called each physics frame. /// </summary> private void FixedUpdate() { Vector3 startPosition = transform.position; // Line begin Vector3 endPosition = startPosition + Vector3.right * 10; // Line end RaycastHit hitResult; // Stores the result // Call Linecast if (Physics.Linecast(startPosition, endPosition, out hitResult)) { Debug.Log($"Linecast hitted: {hitResult.collider.name}"); } } }
Volume casts ?
Until now, we were only casting point/line. Time to start casting volumes!
They are helpful when Raycast doesn’t give you enough precision. Sometimes you would like to check if your character will fit somewhere or the object your holding will hit something on its way.
BoxCast ?
The first volume cast will be the BoxCast method.
To better understand how this method is working, imagine a box in an empty space. Now imagine you’re pushing this box forward, and you wait for it to collide with something.
That’s exactly what the BoxCast method is. It doesn’t matter if this box just scratches its edge or barely touches something. You will know about it.
With this method, you’ll have to pass some additional parameters that define the box – position, size, and rotation.
Code example:
using UnityEngine; /// <summary> /// Use example for BoxCast method. /// </summary> public class BoxExample : MonoBehaviour { /// <summary> /// Called each physics frame. /// </summary> private void FixedUpdate() { Vector3 boxPosition = transform.position; // Box position Vector3 boxHalfSize = Vector3.one * 0.5f; // Half size of the box Quaternion boxRotation = transform.rotation; // Box rotation Vector3 castDirection = transform.forward; // Cast direction RaycastHit hitResult; // Stores the result // Call BoxCast if (Physics.BoxCast(boxPosition, boxHalfSize, castDirection, out hitResult, boxRotation)) { Debug.Log($"BoxCast hitted: {hitResult.collider.name}"); } } }
CapsuleCast ?
The next type of shape cast is the CapsuleCast method.
This method works the same way as BoxCast, but of course, with Capsule rather than Box.
The only quirky thing about this method would be parameters to define capsule.
You have to pass a position of the “bottom” sphere and “top” sphere, and of course, the radius of a capsule.
Code example:
using UnityEngine; /// <summary> /// Use example for CapsuleCast method. /// </summary> public class CapsuleExample : MonoBehaviour { /// <summary> /// Called each physics frame. /// </summary> private void FixedUpdate() { Vector3 bottomSpherePosition = transform.position; // Position of the bottom capsule sphere Vector3 topSpherePosition = Vector3.one * 0.5f; // Position of the top capsule sphere float radius = 0.5f; // Capsule radius Vector3 castDirection = transform.forward; // Cast direction RaycastHit hitResult; // Stores the result // Call CapsuleCast if (Physics.CapsuleCast(bottomSpherePosition, topSpherePosition, radius, castDirection, out hitResult)) { Debug.Log($"CapsuleCast hitted: {hitResult.collider.name}"); } } }
SphereCast ?
The last type is Sphere. Similarly to the box and capsule variant, the SphereCast method will cast spheres!
In this method, we’re only passing the start position and radius of the sphere that we’re casting.
Code example:
using UnityEngine; /// <summary> /// Use example for SphereCast method. /// </summary> public class SphereExample : MonoBehaviour { /// <summary> /// Called each physics frame. /// </summary> private void FixedUpdate() { Vector3 spherePosition = transform.position; // Sphere position float radius = 0.5f; // Sphere radius Vector3 castDirection = transform.forward; // Cast direction RaycastHit hitResult; // Stores the result // Call SphereCast if (Physics.SphereCast(spherePosition, radius, castDirection, out hitResult)) { Debug.Log($"SphereCast hitted: {hitResult.collider.name}"); } } }
Rigidbody’s Sweep Test ?
Whenever methods mention before were not enough, you call also cast your physical object. For that, you need to use Rigidbody.SweepTest method.
But note, that this method will only work when a primitive collider or a convex mesh is attached to the rigidbody.
Thanks to this method, you have a little bit more flexibility with volumetric casts.
Code example:
using UnityEngine; /// <summary> /// Use example for SweepTest method. /// </summary> public class SweepExample : MonoBehaviour { // Reference to the rigidbody component. private Rigidbody rb; /// <summary> /// Called at the beggining. /// </summary> private void Start() { rb = GetComponent<Rigidbody>(); // Get reference to the rigidbody component. } /// <summary> /// Called each physics frame. /// </summary> private void FixedUpdate() { Vector3 castDirection = transform.forward; // Cast direction RaycastHit hitResult; // Stores the result // Call SweepTest if (rb.SweepTest(castDirection, out hitResult)) { Debug.Log($"SweepTest hitted: {hitResult.collider.name}"); } } }
Bonus – CastAll and NonAlloc ?
There are two additional variants to all methods mentioned above – one for receiving all collisions with a cast, and the second which do the same, but you have to provide the buffer for the results.
You can think about CastAll methods as methods that instantiate a new array for results and call NonAlloc methods. At least that’s how I see it… ?
Summary ?
So that’s it about raycasts. If you want to check the documentation go to the Physics and Rigidbody classes.
If you liked the post or have anything more to add, leave the comment in the comment section below!
And if you want to be notified about future content on my blog, you can sign up for my newsletter!
Thanks for reading, and see you next time! ?
Hey Patryk,
Thanks for this writeup. Any idea on the performance ranking of Unity’s raycast methods? For example, is SphereCast any less performant than a Linecast?
Thanks!
Well, shape casts will have some additional overhead as they have to check volumes which Raycast / Linecast don’t need to do. On the other hand, you can’t reliably replace those shape casts with lines 😉