Quick answer: The most common causes are: the LayerMask parameter is filtering out the target's layer, the ray origin is inside the collider you are trying to hit (raycasts do not detect colliders they start inside), the maxDistance is too short, or you are mixing up 2D and 3D raycasts. Use Debug.
Here is how to fix Unity RayCast not hitting collider. You call Physics.Raycast expecting it to detect an enemy, a wall, or the ground — and it returns false every time. No hit, no data, no error message. You have confirmed the collider is there, the object is in the scene, and the ray should be pointing right at it. Raycast failures are notoriously hard to debug because there is no visual feedback by default. The problem is almost always a layer mask misconfiguration, a ray starting inside the target collider, or a 2D/3D mismatch.
The Symptom
Physics.Raycast returns false even though the ray should clearly be hitting a collider. You may have tested by placing a large cube directly in front of the ray origin, and it still returns no hit. Alternatively, the raycast hits some objects but not others, or it worked previously but stopped after you changed layers or reorganized your scene hierarchy.
In 2D games, you may be calling Physics.Raycast instead of Physics2D.Raycast and getting no results because 3D raycasts cannot detect 2D colliders. Another common variant is that the raycast detects the object it originates from (the player's own collider) instead of the intended target.
What Causes This
Unity's raycast system is precise and unforgiving about its parameters. Here are the most common reasons a raycast fails to hit:
- Wrong layer mask — The
layerMaskparameter inPhysics.Raycastis a bitmask, not a layer index. Passing8(meaning layer 8) as the mask actually creates a bitmask of0b00000000000000000000000100000000, which matches layer 3. To correctly target layer 8, you need1 << 8orLayerMask.GetMask("YourLayerName"). - Ray origin inside the collider — A raycast does not detect the collider it starts inside. If your ray origin is at the center of your player and the player has a large collider, the ray may start inside a wall or overlapping object and pass right through it.
- 2D vs 3D mismatch —
Physics.Raycastonly detects 3D colliders (BoxCollider,SphereCollider,MeshCollider).Physics2D.Raycastonly detects 2D colliders (BoxCollider2D,CircleCollider2D). These two physics systems are completely separate and cannot interact. - QueryTriggerInteraction — By default, whether raycasts hit trigger colliders depends on the global setting in Project Settings > Physics > Queries Hit Triggers. If this is unchecked and the target collider has
isTriggerenabled, the raycast will pass through it. - maxDistance too short — If you pass a
maxDistancethat is shorter than the actual distance to the target, the ray stops before reaching the collider. The default overload withoutmaxDistanceusesMathf.Infinity, but overloads that include a layer mask require you to also specify distance. - Collider is disabled or missing — The target object might have its Collider component disabled, or the object may only have a Renderer without a Collider. A visible mesh does not automatically have a collider.
The Fix
Step 1: Visualize the ray with Debug.DrawRay and fix the layer mask. Always start debugging raycasts by drawing them. Debug.DrawRay shows the ray in the Scene view so you can visually confirm its origin, direction, and length. Then verify your layer mask is constructed correctly.
using UnityEngine;
public class RaycastDebugger : MonoBehaviour
{
[SerializeField] private LayerMask targetLayers;
[SerializeField] private float rayDistance = 100f;
private void Update()
{
Vector3 origin = transform.position;
Vector3 direction = transform.forward;
// ALWAYS visualize your ray. Visible in Scene view during Play Mode.
Debug.DrawRay(origin, direction * rayDistance, Color.red);
// Use the LayerMask field — Unity's Inspector handles the bitmask for you
if (Physics.Raycast(origin, direction, out RaycastHit hit, rayDistance, targetLayers))
{
Debug.Log("Hit: " + hit.collider.gameObject.name +
" at distance " + hit.distance);
// Draw a green line to the hit point
Debug.DrawLine(origin, hit.point, Color.green);
}
// WRONG: passing layer index directly
// int enemyLayer = LayerMask.NameToLayer("Enemy"); // returns 8
// Physics.Raycast(origin, direction, out hit, rayDistance, enemyLayer); // BUG!
// CORRECT: convert layer index to bitmask
// int enemyMask = 1 << LayerMask.NameToLayer("Enemy");
// Physics.Raycast(origin, direction, out hit, rayDistance, enemyMask);
// ALSO CORRECT: use LayerMask.GetMask for readability
// int mask = LayerMask.GetMask("Enemy", "Obstacle");
// Physics.Raycast(origin, direction, out hit, rayDistance, mask);
}
}
Step 2: Fix the ray origin and maxDistance. Make sure the ray does not start inside the collider you want to hit. A common pattern is to offset the origin slightly forward from the caster's collider, or to use a specific empty transform as the ray origin point. Also ensure maxDistance is large enough to reach the target.
using UnityEngine;
public class WeaponRaycast : MonoBehaviour
{
[SerializeField] private Transform muzzlePoint;
[SerializeField] private LayerMask hitLayers;
[SerializeField] private float maxRange = 200f;
public void Fire()
{
// Use a dedicated muzzle transform so the ray starts outside the player
Vector3 origin = muzzlePoint.position;
Vector3 direction = muzzlePoint.forward;
// Visualize the ray for debugging
Debug.DrawRay(origin, direction * maxRange, Color.yellow, 1f);
if (Physics.Raycast(origin, direction, out RaycastHit hit, maxRange, hitLayers))
{
Debug.Log("Hit: " + hit.collider.name + " on layer " +
LayerMask.LayerToName(hit.collider.gameObject.layer));
// Apply damage if the target has a health component
var health = hit.collider.GetComponent<HealthComponent>();
if (health != null)
health.TakeDamage(25);
}
else
{
Debug.Log("Raycast missed. Origin: " + origin +
", Direction: " + direction +
", Distance: " + maxRange);
}
}
// Ignore the caster's own colliders
public void FireIgnoringSelf()
{
Vector3 origin = muzzlePoint.position;
Vector3 direction = muzzlePoint.forward;
RaycastHit[] hits = Physics.RaycastAll(origin, direction, maxRange, hitLayers);
foreach (RaycastHit hit in hits)
{
// Skip hits on our own GameObject or children
if (hit.transform.IsChildOf(transform))
continue;
Debug.Log("First valid hit: " + hit.collider.name);
break;
}
}
}
Step 3: Match 2D vs 3D and configure trigger interaction. If your game uses 2D physics, you must use Physics2D.Raycast instead of Physics.Raycast. The API is slightly different — Physics2D.Raycast returns a RaycastHit2D struct, and you check its collider property for null instead of checking a boolean return value. For trigger colliders, explicitly set QueryTriggerInteraction.
using UnityEngine;
public class RaycastExamples : MonoBehaviour
{
[SerializeField] private LayerMask targetLayers;
// 3D Raycast with explicit trigger handling
private void Raycast3D()
{
Vector3 origin = transform.position;
Vector3 direction = transform.forward;
// Explicitly include trigger colliders in the raycast
if (Physics.Raycast(origin, direction, out RaycastHit hit, 100f,
targetLayers, QueryTriggerInteraction.Collide))
{
Debug.Log("3D hit: " + hit.collider.name);
Debug.Log("Is trigger: " + hit.collider.isTrigger);
}
}
// 2D Raycast — completely separate physics system
private void Raycast2D()
{
Vector2 origin = transform.position;
Vector2 direction = Vector2.right;
// Physics2D.Raycast returns a RaycastHit2D struct
RaycastHit2D hit = Physics2D.Raycast(origin, direction, 100f, targetLayers);
// Check the collider property, not a boolean return value
if (hit.collider != null)
{
Debug.Log("2D hit: " + hit.collider.name);
Debug.Log("Hit point: " + hit.point);
Debug.Log("Hit distance: " + hit.distance);
}
// Visualize in 2D
Debug.DrawRay(origin, direction * 100f, Color.red);
}
// Camera-based raycast for mouse picking
private void MouseRaycast()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
// Debug the ray
Debug.DrawRay(ray.origin, ray.direction * 500f, Color.cyan);
if (Physics.Raycast(ray, out RaycastHit hit, 500f, targetLayers))
{
Debug.Log("Mouse hit: " + hit.collider.name);
}
}
}
A quick summary of the debugging checklist for raycast issues:
- Use
Debug.DrawRayto visualize the ray in the Scene view. - Use a
LayerMaskserialized field instead of hardcoded layer numbers. - Confirm the target has an enabled Collider component (not just a Renderer).
- Ensure the ray origin is outside all colliders you want to detect.
- Match 2D/3D:
Physics.RaycastforCollider,Physics2D.RaycastforCollider2D. - Set
QueryTriggerInteractionexplicitly when you need to hit or ignore triggers. - Check that
maxDistanceis long enough to reach the target.
Related Issues
See also: Fix: Unity OnCollisionEnter Not Being Called.
See also: Fix: Unity ScriptableObject Data Lost After Exiting Play Mode.
Debug.DrawRay is your best friend. Always visualize before debugging logic.