Unity Term Book
Physics

Raycasting

Raycasting casts an invisible ray in a direction to find Colliders — the foundation of shooting, ground checks, mouse picking, and line-of-sight gameplay.

Imagine...

A Raycast is a flashlight in the dark. You shine it one way — the beam travels until it hits something. Then it reports what it hit, how far, where, and which way the surface faces. In a shooter, a Raycast stands in for a real physics bullet — cheaper, faster, more precise.

The concept in detail

Physics.Raycast() takes an origin, a direction, and returns true if the ray hits a Collider. Details land in a RaycastHit: hit position ( .point), surface direction (.normal), distance ( .distance), and the object (.collider).

Unity ships several variants: Physics.RaycastAll() returns every Collider along the path (not just the nearest), Physics.SphereCast() sweeps a sphere (smoother character “snapping”), and Physics.BoxCast() sweeps a box. From Unity 2022+, Physics.RaycastCommand can run raycasts in parallel on the Job System.

Performance: Raycasts are not free — each call walks the broadphase BVH. Always pass a LayerMask and a maxDistance. Avoid looping them every frame — an AI can raycast 4 directions every 0.2s instead of every frame.

Common uses: shooting (hitscan, no Rigidbody bullet), ground check (is the character standing before a jump), mouse picking ( Camera.ScreenPointToRay() turns a click into a 3D ray), line of sight (does anything block the AI from the player).

Raycast variants

Raycast

A straight ray; returns only the nearest Collider. Use it for almost everything.

Physics.Raycast()

SphereCast

A spherical sweep — better for characters, large weapons, and wide-area detection.

Physics.SphereCast()

RaycastAll

Returns all Colliders along the path. Use for armor-piercing bullets, lights through glass.

Physics.RaycastAll()

Hands-on steps

1

Pick origin and direction

Often Camera.main.transform.position and .forward for FPS, or Vector3.down for a ground check.

2

Declare a RaycastHit

RaycastHit hit; — then pass out hit into Physics.Raycast(). Keep it outside Update to avoid GC.

3

Set a LayerMask

Assign it in the Inspector, or LayerMask.GetMask("Enemy", "Ground") so you only test what you need.

4

Cap maxDistance

Always pass a max range — an infinite ray tests the whole scene. Example: gun range 50f, ground check 1.2f.

5

Draw a Debug Ray in Scene view

Debug.DrawRay(origin, direction * maxDist, Color.green) — visible while playing, no effect in builds.

Interactive simulator

Move the mouse over the canvas to aim the ray. Drag obstacles around.

Move the mouse...

No hit yet

Code example

Basic

Hitscan shooting — fire without a Rigidbody bullet.

using UnityEngine;

public class HitscanGun : MonoBehaviour
{
  public float range = 50f;
  public int damage = 25;
  public LayerMask shootMask;
  public ParticleSystem muzzleFlash;

  Camera cam;
  RaycastHit hit; // Declare outside Update to avoid GC

  void Start() => cam = Camera.main;

  void Update()
  {
      if (Input.GetButtonDown("Fire1")) Fire();
  }

  void Fire()
  {
      muzzleFlash.Play();

      // Ray from camera center, forward
      if (Physics.Raycast(cam.transform.position,
                         cam.transform.forward,
                         out hit, range, shootMask))
      {
          Debug.Log("Hit: " + hit.collider.name +
                     " at " + hit.distance.ToString("F1") + "m");

          hit.collider.GetComponent<Health>()
             ?.TakeDamage(damage);
      }
  }
}

Code example

Advanced

Accurate ground check plus mouse-to-world picking — the two most common use cases.

using UnityEngine;

public class RaycastUtils : MonoBehaviour
{
  [Header("Ground Check")]
  public float groundCheckDist = 1.2f;
  public LayerMask groundLayer;
  bool isGrounded;

  [Header("Mouse Picking")]
  public LayerMask clickable;

  Camera cam;
  RaycastHit hit;

  void Awake() => cam = Camera.main;

  void Update()
  {
      // Ground check every frame — SphereCast is smoother than Raycast
      isGrounded = Physics.SphereCast(
          transform.position, 0.4f,
          Vector3.down, out hit,
          groundCheckDist, groundLayer
      );

      // Click → world position
      if (Input.GetMouseButtonDown(0))
      {
          Ray ray = cam.ScreenPointToRay(Input.mousePosition);
          if (Physics.Raycast(ray, out hit, 100f, clickable))
          {
              Debug.Log("Clicked: " + hit.collider.name);
              // Move the character to hit.point
              MoveTo(hit.point);
          }
      }
  }

  void OnDrawGizmosSelected()
  {
      Gizmos.color = isGrounded ? Color.green : Color.red;
      Gizmos.DrawLine(transform.position,
          transform.position + Vector3.down * groundCheckDist);
  }
}

📌 Quick recap

  • Always pass a LayerMask + maxDistance
  • Declare RaycastHit once outside Update (avoid GC)
  • Camera.ScreenPointToRay() for mouse-to-3D
  • Debug.DrawRay() to see the ray in Scene view
  • SphereCast is smoother than Raycast for character movement

⚠️ Common mistakes

  • ❌ The ray hits yourself (self-hit)

    Origin sits inside the shooter’s Collider — always returns true

    ✅ Offset the origin (+0.1f along forward), or ignore your own layer

  • ❌ Raycast every frame with no MaxDistance

    An infinite ray tests the whole scene and tanks FPS

    ✅ Always pass a maxDistance that matches the use case