Table of Contents

Queries

Asking the world what is there, without stepping it. Every query on this page allocates nothing, including the callback forms.

Question Call
What does this ray hit first? world.RaycastClosest
What does this ray pass through? world.Raycast with a callback
What is inside this box? world.OverlapBox, world.OverlapBounds
Does this ray hit that shape? shape.Raycast
How far can this capsule move? world.CastCapsule
What is this capsule touching? world.CollideCapsule — see Characters

The closest hit

RaycastHit hit = world.RaycastClosest(muzzle, aim * 100.0f);

if (hit.Hit)
{
    ulong entity = hit.Shape.Body.UserData;
    var zone = (HitZone)hit.Shape.UserData;

    Damage(entity, zone == HitZone.Head ? 100 : 25);
    SpawnDecal(hit.Point, hit.Normal);
}

The second argument is a vector, not a direction: its length is the range. Fraction is how far along it the hit was, from zero to one, so multiply by that vector's length to get a distance.

RaycastHit also carries TriangleIndex and ChildIndex for hits against meshes and compounds, and UserMaterialId for whatever you tagged the surface with.

Ray casts that need a decision per hit

Ignoring the shooter, collecting every hit, stopping early — implement IRaycastCallback on a struct:

struct IgnoreSelf : IRaycastCallback
{
    public Body Self;
    public RaycastHit Nearest;

    public RaycastAction OnHit(in RaycastHit hit)
    {
        if (hit.Shape.Body == Self)
        {
            return RaycastAction.Ignore;
        }

        Nearest = hit;
        return RaycastAction.ClipTo(hit.Fraction);   // keep only closer hits
    }
}

var callback = new IgnoreSelf { Self = player };
world.Raycast(muzzle, aim * 100.0f, ref callback);

Shapes arrive in no particular order. What you return decides what happens next:

RaycastAction Effect
Ignore Pretend the shape is not there and carry on
ClipTo(hit.Fraction) Shorten the ray to end here; only closer shapes are reported afterwards
Continue Record it and carry on, near and far
Stop End the cast now, keeping what was gathered

Returning ClipTo from every hit is a closest-hit search, which is what RaycastClosest does for you.

A struct rather than a delegate, because the query is generic over the callback type: the JIT specialises it and inlines your OnHit into the dispatcher, so nothing is allocated and nothing has to be kept alive across the native transition. See the native layer.

The world is locked while a query runs. Collect what you need and create or destroy bodies after it returns.

Overlaps

struct CountBodies : IOverlapCallback
{
    public int Count;

    public bool OnOverlap(Shape shape)
    {
        Count++;
        return true;   // false stops the search
    }
}

var callback = new CountBodies();
world.OverlapBox(explosionCentre, new Vector3(5.0f), ref callback);

This is a broad-phase query: it tests bounding boxes, not geometry, so it can report a shape whose box overlaps and whose geometry does not. Narrow it yourself when you need exactness — a distance test against shape.ClosestPointTo is usually enough.

OverlapBounds takes a BoundingBox directly, which is the form to use when you already have one from body.Bounds or shape.Bounds.

Filtering a query

Every query takes an optional QueryFilter, which works exactly like a collision filter: the query sees a shape when the categories agree in both directions.

var visibleToBullets = new QueryFilter(
    categories: (ulong)Layers.Bullet,
    collidesWith: (ulong)(Layers.World | Layers.Enemy));

world.RaycastClosest(muzzle, aim * 100.0f, visibleToBullets);

Passing null, which is the default, tests against everything.

Casting against one shape

RaycastHit hit = shape.Raycast(origin, direction * 10.0f);

No broad phase, no filter — just this shape. Useful when you already know what you are testing against, such as re-checking the shape a previous query returned.

Explosions

Not a query, but it belongs with them: Explode applies a radial impulse to everything within reach, scaled by how much of each shape faces the blast.

world.Explode(centre, radius: 5.0f, impulsePerArea: 300.0f, falloff: 2.0f);

Only spheres, capsules and hulls respond. A negative impulsePerArea implodes.