Skip to content

Queries

A query asks the physics scene what is there, without simulating anything. Queries are the workhorse behind shooting, line of sight, ground checks, interaction prompts, and area-of-effect damage.

All three run on the game thread and read the latched physics state.

A raycast shoots a line through the world and returns the first thing it hits.

The two languages describe the ray differently. C++ fills in a settings struct with a start and an end point; C# takes an origin, a direction, and a distance, and normalizes the direction for you.

const FVector3 From = Context.GetEntityTransform(Entity).GetWorldLocation();
const FVector3 Dir = Context.GetEntityTransform(Entity).GetForward();
SRayCastSettings Settings;
Settings.Start = From;
Settings.End = From + Dir * 100.0f;
Settings.AddIgnoredBody(Context.GetEntityBodyID(Entity));
if (TOptional<SRayResult> Hit = Context.GetPhysicsScene()->CastRay(Settings))
{
LOG_INFO("hit {} at {}", (uint32)Hit->Entity, Hit->Location);
}

SRayCastSettings also carries LayerMask to restrict the query to collision layers, bIgnoreSelf, and bDrawDebug / DebugDuration to draw the ray in the viewport.

The hit result carries the same information under different names.

C++ SRayResultC# RaycastHitMeaning
EntityEntityThe entity that was hit
LocationPointThe world-space hit point (FVector3)
NormalNormalThe surface normal at the hit
DistanceDistanceDistance from the origin to the hit
FractionFractionHow far along the ray, 0 at the origin, 1 at the end
BodyIDBodyIdThe Jolt body id that was hit
Start / EndThe ray that produced the hit
BoneIndexSkeleton bone for a ragdoll body, INDEX_NONE otherwise

A sphere cast sweeps a sphere along a line instead of an infinitely thin ray, useful for thick projectiles, character probes, and “is there room here” checks. It returns every hit, sorted near to far.

SSphereCastSettings Settings;
Settings.Start = From;
Settings.End = From + Dir * 100.0f;
Settings.Radius = 0.5f;
Settings.AddIgnoredBody(Context.GetEntityBodyID(Entity));
for (const SRayResult& Swept : Context.CastSphere(Settings))
{
LOG_INFO("swept into {}", (uint32)Swept.Entity);
}

An overlap returns every entity whose body intersects a shape right now, the core AI-perception, area-of-effect, and trigger primitive.

C++ appends into a vector you own, so a per-frame query can reuse its storage. C# returns a fresh array.

TVector<uint32> Ignore { Context.GetEntityBodyID(Entity) };
TVector<entt::entity> Nearby;
Context.GetPhysicsScene()->OverlapSphere(Center, 5.0f, Ignore, Nearby);
Context.GetPhysicsScene()->OverlapBox(Center, HalfExtents, Rotation, Ignore, Nearby);

Results are appended and de-duplicated, so clear the vector between queries if you do not want them to accumulate.

C++ queries go through Physics::IPhysicsScene. From a system, get it with Context.GetPhysicsScene(), which returns null in a world that does not simulate, so null-check it. CastSphere is mirrored directly onto FSystemContext as a convenience; CastRay, CastRayAll, CollidePoint, and the overlaps are on the scene.

Outside a system, CWorld exposes GetPhysicsScene(), CastRay, and CastSphere on itself.