Recursive AI

Query a 3D sphere overlap in C#

onegame is a free, open-source game engine for .NET from Recursive AI. MIT or Apache-2.0, no editor required.

A sphere overlap finds one body intersecting a spherical area, not a list of all hits.

Terminal
dotnet add package RecursiveAI.OneGame.Physics

Requires .NET 10 (net10.0); .NET 9 and earlier aren’t supported.

Fixed and FVec3 are onegame’s deterministic fixed-point number and vector types.

C#
using OneGame.Core;
using OneGame.Physics;
 
var space = new PhysicsSpace3D();
space.AddSphere(Fixed.One,
    new FVec3(2, 0, 0));
bool found = space.OverlapSphere(
    FVec3.Zero, Fixed.FromInt(2),
    out var hit);
Console.WriteLine(found);

Prints whether the area overlaps a body.

Text
True

Unzip the example, then dotnet run.

The full program

The download creates a static sphere on layer 2, checks an overlapping area, then checks an empty area. It reads the returned body only when the query succeeds.

C#
using OneGame.Core;
using OneGame.Physics;
 
var space = new PhysicsSpace3D();
var target = space.AddSphere(
    Fixed.One, new FVec3(2, 0, 0),
    new BodyOptions3D
    {
        Kind = BodyKind.Static, Layer = 2
    });
if (space.OverlapSphere(
    FVec3.Zero, Fixed.FromInt(2),
    out var hit, layers: 1u << 2))
    Console.WriteLine(
        $"Target: {hit.Body == target}");
else
    Console.WriteLine("No overlap");
bool distant = space.OverlapSphere(
    new FVec3(20, 0, 0),
    Fixed.One, out _);
Console.WriteLine($"Distant overlap: {distant}");
Console.WriteLine($"Steps: {space.StepCount}");

dotnet run prints:

Text
Target: True
Distant overlap: False
Steps: 0

Steps: 0 means neither overlap query advances the simulation.

A miss returns false and sets hit to its default value; this API returns one matching body, not a collection.

Variations

Exclude the target’s layer. Append this to the full program:

C#
bool excluded = space.OverlapSphere(
    FVec3.Zero, Fixed.FromInt(2),
    out _, layers: 1u << 1);
Console.WriteLine($"Other layer: {excluded}");
Text
Other layer: False

The short answer

Use PhysicsSpace3D.OverlapSphere(center, radius, out hit, layers). It returns true when it finds a matching body and supplies one RayHit3D. It returns false with a default hit when nothing matches. This wrapper does not expose an array of overlapping bodies, so it answers “is there a match here?” rather than “give me everything in this radius.”

What is overlap sphere in physics?

An overlap checks a spherical area at one position. There is no direction or travel distance to supply. In the snippet at the top, the query is centered at the origin with radius two. The body is a sphere of radius one centered at X = 2, so the two volumes overlap. The body’s center does not have to be inside the query for their surfaces to intersect.

The full program repeats that check with an explicit layer, then moves the query center to X = 20. That second area is empty and returns false. No simulation step is required to ask either question: the printed step count remains zero. Neither call moves the target or adds a query body to the space.

The out parameter is a RayHit3D, the same result type used by the space’s ray and sphere-cast queries. It has Body, Point, Normal and Distance fields. For an existence test, use the Boolean. To identify the match, read Body inside the successful branch, as the download does. Do not interpret the shared result type as a promise that an overlap has ray-travel semantics: this query has no path to travel.

If several bodies overlap the area, this method still supplies just one match. Its wrapper comment says “Finds a matching body overlapping a sphere,” not “nearest” and not “all.” Do not repeatedly call it expecting a new body each time, and do not use its single result as an explosion-damage list. Choose it when a single match is enough for your game rule.

Why is an overlap sphere failing to detect ground?

First check the query’s geometry and the space you are querying. A center is a local physics position, not a screen coordinate or a global position after rebasing. A radius is a Fixed length. The sample constructs its own space and body, removing those uncertainties; in an existing game, query the registered PhysicsSpace3D that actually holds your ground.

Then check the layer mask. The download places its body on layer 2 and passes 1u << 2. That expression selects the bit for layer 2; the integer 2 alone would select layer 1. The variation switches the query to layer 1 and shows a miss without changing either shape. Omitting the argument selects all layer bits.

Finally, distinguish an overlap from a sweep or a grounded character result. An overlap asks whether the spherical region intersects something now. A sphere cast asks what a sphere meets along a direction. Neither single query supplies a full movement policy. For a walking capsule with collide-and-slide behavior, use the character API described in the physics guide, rather than assuming one overlapping ground body determines every slope or movement decision.

All onegame recipes