Guides Physics 2D Queries 2D Physics Queries

Physics 2D Queries 3 min read Updated Apr 2026

2D Physics Queries

Physics queries let gameplay ask the world a question right now.

This is the right tool when you need things like:

  • line of sight
  • ground probes
  • target selection
  • interaction ranges
  • explosion areas
  • predictive movement checks

Unlike callbacks, queries happen when your code asks for them. Unlike contact queries, they are not limited to what you are already touching.

Physics query overview

Quick Reference

Lenga exposes these 2D query families:

  • raycast(...)
  • raycastAll(...)
  • circleCast(...)
  • circleCastAll(...)
  • boxCast(...)
  • boxCastAll(...)
  • overlapPoint(...)
  • overlapCircleAll(...)
  • overlapBoxAll(...)

All of them support:

  • trigger filtering
  • optional layer masks

A Note on 2D Coordinates

The PHP API uses Vector3 for 2D physics queries.

In 2D gameplay, the z value is typically 0.0.

use Lenga\Engine\Core\Vector3;

$origin = new Vector3(0.0, 0.0, 0.0);
$direction = new Vector3(1.0, 0.0, 0.0);

Use raycast(...) for Thin, Precise Probes

Raycasts are the best starting point when you want "first thing in this direction."

Great fits:

  • wall checks
  • downward ground probes
  • weapon traces
  • enemy line of sight
use Lenga\Engine\Core\Physics2D;
use Lenga\Engine\Core\Vector3;

$origin = $gameObject->transform->position;
$direction = new Vector3(0.0, -1.0, 0.0);

$hit = Physics2D::raycast($origin, $direction, 1.5, false);

if ($hit !== null) {
    Debug::info('Hit ' . ($hit->gameObject?->name ?? 'Unknown'));
}

Use raycastAll(...) When You Need Every Hit

Sometimes the first hit is not enough.

Examples:

  • bullet penetration
  • visibility tools
  • editor picking tools
  • finding everything between two points
$hits = Physics2D::raycastAll($origin, $direction, 10.0, true);

foreach ($hits as $hit) {
    Debug::info('Along ray: ' . ($hit->gameObject?->name ?? 'Unknown'));
}

Use circleCast(...) for Forgiving Movement Checks

Circle casts are often better than rays when you want some thickness.

They are especially good for:

  • rounded characters
  • forgiving ground checks
  • rolling projectiles
  • "would this movement hit anything?" checks
$groundHit = Physics2D::circleCast(
    $gameObject->transform->position,
    0.35,
    new Vector3(0.0, -1.0, 0.0),
    0.8,
    false
);

if ($groundHit !== null) {
    // We found support below the body.
}

Use boxCast(...) When Your Gameplay Shape Is Rectangular

Box casts are a strong fit for:

  • platformer body movement
  • melee hit volumes
  • push boxes
  • rectangular sensors
$hit = Physics2D::boxCast(
    $gameObject->transform->position,
    new Vector3(1.0, 2.0, 0.0),
    new Vector3(1.0, 0.0, 0.0),
    2.0,
    false
);

If your character footprint is box-like, a box cast often matches gameplay better than a ray or circle.

Use overlapPoint(...) for Picking

This is ideal for:

  • clicking world objects
  • checking if a spawn point is occupied
  • testing a cursor against colliders
$collider = Physics2D::overlapPoint($worldMousePosition, true);

if ($collider !== null) {
    Debug::info('Selected collider on ' . $collider->gameObject->name);
}

Use overlapCircleAll(...) for Radius Checks

This is often the cleanest way to build:

  • explosions
  • magnetic pickups
  • enemy awareness radii
  • interaction prompts
$targets = Physics2D::overlapCircleAll(
    $gameObject->transform->position,
    3.0,
    true
);

foreach ($targets as $target) {
    Debug::info('In radius: ' . $target->gameObject->name);
}

Use overlapBoxAll(...) for Area Checks With Hard Edges

Good fits:

  • room sensors
  • rectangle hit zones
  • placement tests
  • puzzle rule areas
$colliders = Physics2D::overlapBoxAll(
    $gameObject->transform->position,
    new Vector3(4.0, 2.0, 0.0),
    false
);

Layer Masks Keep Queries Focused

Use Physics2D::layerMask(...) when a query should only care about certain layers.

use Lenga\Engine\Core\Physics2D;

$groundMask = Physics2D::layerMask(3);
$enemyMask = Physics2D::layerMask(2);

$groundHit = Physics2D::raycast($origin, $down, 1.0, false, $groundMask);
$enemyHits = Physics2D::overlapCircleAll($origin, 4.0, true, $enemyMask);

This is one of the easiest ways to stop a query from becoming noisy.

Trigger Filtering

All of these queries can include or exclude triggers.

Use true when trigger zones matter to the query.

Use false when you only want solid geometry.

$solidHit = Physics2D::raycast($origin, $direction, 5.0, false);
$triggerAwareHit = Physics2D::raycast($origin, $direction, 5.0, true);

What a RaycastHit2D Gives You

Cast queries return RaycastHit2D objects with:

  • gameObject
  • collider
  • point
  • normal
  • distance
  • fraction

That means a query result is useful for both decision making and effects placement.

if ($hit !== null) {
    $point = $hit->point;
    $normal = $hit->normal;

    // Use the point for impact VFX and the normal for orientation.
}

Picking the Right Query

Use this quick mental model:

  • raycast = thin line
  • circleCast = moving rounded volume
  • boxCast = moving rectangular volume
  • overlapPoint = exact point check
  • overlapCircleAll = radius search
  • overlapBoxAll = rectangular area search

Good Habits

  1. Keep query distances short and intentional.
  2. Use layer masks early.
  3. Prefer the shape that matches gameplay, not the one with the shortest signature.
  4. Use contact queries instead when the question is about current touch state.