Quick answer: Physics.OverlapSphere and OverlapBox query the physics broadphase as it stood at the last fixed step. Fast-moving colliders that have moved since that step are missed, and very fast colliders can tunnel completely through the query volume between two steps. Run the query in FixedUpdate, call Physics.Sync() after teleporting any collider you want immediately discoverable, set fast Rigidbodies to ContinuousDynamic collision detection, and double-check the layer mask is what you expect.
Here is how to fix Unity physics overlaps when they miss fast-moving colliders. You have a damage volume that uses OverlapSphere to find every enemy in range. It works perfectly until you fight an enemy that dashes through the volume at high speed, and the dashing enemy takes no damage. Or your projectile lands, you call OverlapBox at the impact point, and an enemy that you can clearly see touching the box gets no callback. The physics system is internally consistent — it is just answering a question about a slightly different moment in time than you expected.
The Symptom
The bug splits into a few diagnostically distinct cases depending on how the collider was missed:
Fast collider crosses the query volume undetected. A projectile or fast enemy passes through your overlap region, but the query returns an empty array. The collider was on one side of the query at the previous step, on the other side at the next step, and at the moment your query ran it was actually inside the volume — the broadphase just had not been updated to reflect it.
Just-teleported collider is missed. You set transform.position on an object, then immediately do an OverlapSphere centered there. The query misses every collider that should be near the new position because the physics broadphase still thinks the object is at the old position.
Hits found inconsistently. The query hits an object every other frame, or only when the framerate drops. This is the FixedUpdate timing case — you are running the query in Update, and depending on how many fixed steps fall within the previous frame, the broadphase you query against is sometimes fresh and sometimes stale.
Wrong objects returned. The query returns colliders, but not the ones you expected. This is usually a layer mask issue rather than a fast-moving issue — you typed 1 << LayerMask.NameToLayer("Enemy") wrong somewhere, or you set the QueryTriggerInteraction to Ignore when you wanted Collide.
What Causes This
Broadphase staleness. The physics engine maintains a broadphase data structure (a sweep-and-prune or BVH) that lists every collider’s axis-aligned bounding box. This structure is rebuilt during Physics.Simulate, which runs at the start of every fixed step. Between fixed steps, transforms can change (you wrote to transform.position, or another script did) and the broadphase does not know. Overlap queries consult the broadphase, so they see the old positions.
Tunneling. Even with the broadphase fully up to date, a collider moving at v > size / fixedDelta traverses more than its own width per fixed step. If your query happens to fire on a step when the collider is not inside the volume, but it was inside between the last step and this one, the overlap is missed entirely. This is the classic tunneling problem and applies to every instantaneous query.
Wrong update phase. Calling overlap queries from Update or LateUpdate means the query runs against whatever broadphase state existed at the most recent fixed step, which may be 0–3 fixed steps in the past depending on framerate. Running queries from FixedUpdate guarantees the broadphase is current for that step.
Inactive collider. A collider on a GameObject that was just activated still needs a fixed step (or a manual Physics.SyncTransforms) before the broadphase knows about it. Calling OverlapSphere immediately after instantiation misses the new collider.
The Fix
Step 1: Move overlap queries into FixedUpdate. If your query is part of a damage tick, an AOE check, a sensor, or any logic that should be authoritative, run it from FixedUpdate, not Update. The broadphase is always fresh at the start of FixedUpdate, and your query timing aligns with the rest of the physics simulation.
Step 2: Call Physics.Sync after teleporting. Whenever you write transform.position or rb.position outside the physics simulation step (the “teleport” pattern), call Physics.SyncTransforms() or Physics.Sync() before any overlap query that depends on the new position:
using UnityEngine;
public class ImpactDamage : MonoBehaviour
{
[SerializeField] private float radius = 3f;
[SerializeField] private LayerMask damageMask;
private readonly Collider[] hitsBuffer = new Collider[64];
public void ApplyAt(Vector3 worldPosition)
{
// Force the broadphase to reflect any pending transform writes.
Physics.SyncTransforms();
int count = Physics.OverlapSphereNonAlloc(
worldPosition, radius, hitsBuffer,
damageMask, QueryTriggerInteraction.Collide);
for (int i = 0; i < count; i++)
{
if (hitsBuffer[i].TryGetComponent(out Damageable d))
{
d.TakeDamage(25);
}
}
}
}
Note the use of OverlapSphereNonAlloc with a pre-allocated hitsBuffer. This avoids allocating a new array on every call, which matters when impact damage fires hundreds of times per second.
Step 3: Set fast Rigidbodies to ContinuousDynamic. On any Rigidbody whose velocity can carry it more than its own collider width per fixed step (e.g., projectiles, dashing enemies, vehicles), open the Rigidbody inspector and change Collision Detection from Discrete to Continuous Dynamic. Continuous Dynamic sweeps the collider through its motion path each fixed step, so the broadphase contains an envelope that covers the whole sweep, and overlap queries cannot miss the intersection.
Step 4: Verify your layer mask. A surprising fraction of “OverlapSphere is missing colliders” bug reports are actually layer mask bugs. Common mistakes: passing the layer index instead of 1 << index, using ~0 when you wanted 0, or forgetting that the Physics layer collision matrix can disable interactions even when the mask allows them.
Sweep-Based Detection for High Velocities
For very high velocities — bullets, hyperspeed projectiles — even ContinuousDynamic can fail because it only sweeps within the fixed step. The robust approach is to track the projectile’s previous and current position each step and sweep a capsule between them yourself:
using UnityEngine;
public class SweepBullet : MonoBehaviour
{
[SerializeField] private float speed = 200f;
[SerializeField] private float radius = 0.05f;
[SerializeField] private LayerMask hitMask;
private Vector3 lastPos;
private readonly RaycastHit[] hits = new RaycastHit[8];
private void Awake() => lastPos = transform.position;
private void FixedUpdate()
{
Vector3 next = lastPos + transform.forward * speed * Time.fixedDeltaTime;
Vector3 delta = next - lastPos;
float distance = delta.magnitude;
// Sphere-cast through the entire frame's motion path.
int count = Physics.SphereCastNonAlloc(
lastPos, radius, delta.normalized, hits,
distance, hitMask, QueryTriggerInteraction.Collide);
if (count > 0)
{
RaycastHit closest = hits[0];
for (int i = 1; i < count; i++)
{
if (hits[i].distance < closest.distance) closest = hits[i];
}
transform.position = closest.point;
OnHit(closest);
return;
}
transform.position = next;
lastPos = next;
}
private void OnHit(RaycastHit hit) { /* impact logic */ }
}
This pattern guarantees no collider in the swept volume can be missed, regardless of speed. It is more expensive than a discrete OverlapSphere but is the only correct answer for projectiles whose velocity exceeds their size per step.
Debugging With Physics Debugger
Open Window > Analysis > Physics Debugger. Enable Show Collision Geometry. You can now see the actual broadphase bounds the engine uses for queries. Pause the editor mid-frame and confirm the collider you expected is where you expected. If the visual mesh has moved but the broadphase outline has not, you have caught a Physics.Sync issue red-handed.
“Every overlap query is a question about the past. The further your code drifts from the last fixed step, the older the answer. Run physics queries from physics callbacks.”
Related Issues
If your overlap query returns colliders but the data on them is wrong (old positions, last-frame state), see Physics Overlap Returning Stale Results. For physics-driven movement that vibrates or jitters, the cause is often the same fixed-step / variable-frame mismatch.
FixedUpdate + Physics.SyncTransforms + ContinuousDynamic + the right layer mask — if any of those four is wrong, OverlapSphere will lie to you.