Quick answer: Check if return value equals buffer length — that means hits may have been truncated. Grow the buffer (double size) and retry, or use a buffer sized larger than typical max hits.
An AoE damage spell uses Physics.OverlapSphereNonAlloc with a 16-Collider buffer. In dense fights with 20+ enemies, only 16 take damage. Quiet truncation.
NonAlloc Semantics
OverlapSphereNonAlloc fills your provided Collider[] buffer up to its length. Return value = number filled. If returned == buffer.Length, the physics engine had more hits but stopped writing. Hits beyond your buffer are lost.
The Fix: Detect and Grow
Collider[] _buffer = new Collider[16];
int CountAffected(Vector3 center, float radius, LayerMask mask) {
int count;
while (true) {
count = Physics.OverlapSphereNonAlloc(center, radius, _buffer, mask);
if (count < _buffer.Length) break;
// Buffer was full; might have missed hits. Grow and retry.
_buffer = new Collider[_buffer.Length * 2];
}
return count;
}
Detect saturation and double the buffer. The next call captures all hits. Subsequent queries reuse the new larger buffer.
Avoid Growth Per Frame
If your max realistic count is 64, allocate that size at startup and never grow. Growth at runtime is fine for occasional spikes but allocations during gameplay are perf taxes.
SyncTransforms for Accurate Counts
If you mutate transforms (move colliders) and immediately query, results may use stale positions. Call Physics.SyncTransforms before the query to ensure the broadphase reflects the latest changes:
Physics.SyncTransforms(); // expensive; call only when needed
int count = Physics.OverlapSphereNonAlloc(...);
Heavy operation; do it only when fresh queries on moved objects are required.
Verifying
Cast a sphere into a known cluster of 50 enemies. Should report 50 hits (assuming all fit in the buffer). If reports 16, buffer is too small and growing detected.
“NonAlloc truncates silently. Check return == buffer.Length and grow, or pre-size for your worst case.”
Document the assumed max count next to the buffer field — future maintainers don’t guess what size is safe to use.