They do not ask:
- what would I hit?
- what just entered?
They ask:
What am I touching right now?
That makes them useful for grounded checks, wall checks, overlapping hazard logic, and any other situation where current contact state matters more than a single collision event.
Available Methods
Lenga exposes contact queries on:
BoxCollider2DCircleCollider2DRigidbody2D
Shared methods:
isTouching(...)getContacts(...)
Additional rigidbody helper:
isGrounded(...)
Use isTouching(...) for Fast Yes-or-No Checks
This is the lightest option when you only need an answer, not the full contact list.
use Lenga\Engine\Core\BoxCollider2D;
$collider = $gameObject->getComponent(BoxCollider2D::class);
if ($collider?->isTouching(false)) {
// Something solid is touching this collider right now.
}
That is a good fit for:
- "am I inside a trigger?"
- "is this hazard already touching the player?"
- "is this body standing on something?"
Use getContacts(...) When You Need Details
getContacts(...) returns Collision2D objects, so you can inspect who you touched and how.
$contacts = $collider?->getContacts(false) ?? [];
foreach ($contacts as $contact) {
$otherName = $contact->otherGameObject?->name ?? 'Unknown';
$normal = $contact->normal;
Debug::info(
'Touching ' . $otherName
. ' with normal ' . $normal->x . ', ' . $normal->y
);
}
This is where contact queries become more than a boolean. They let you inspect the actual contact state and decide what to do next.
Rigidbody2D::isGrounded(...)
Grounded checks are common enough that Rigidbody2D exposes them directly.
use Lenga\Engine\Core\Rigidbody2D;
$body = $gameObject->getComponent(Rigidbody2D::class);
if ($body?->isGrounded()) {
// Allow jump
}
You can also tune how strict the slope support should be:
if ($body?->isGrounded(0.75, false)) {
// Require a flatter supporting surface
}
This is especially useful for:
- platformer jump gating
- landing logic
- checking whether a character is on a steep slope
Collider Queries vs Rigidbody Queries
Use collider queries when you care about one specific shape.
Use rigidbody queries when you care about the whole body and the contacts that body currently owns.
Example:
$box = $gameObject->getComponent(BoxCollider2D::class);
$body = $gameObject->getComponent(Rigidbody2D::class);
$colliderTouching = $box?->isTouching(false) ?? false;
$bodyGrounded = $body?->isGrounded() ?? false;
Both are valid. They just answer slightly different questions.
Trigger Filtering
By default, contact queries include triggers.
If you want only solid contacts:
$touchingSolid = $body?->isTouching(false);
If you want triggers included:
$touchingAnything = $body?->isTouching(true);
Layer Filtering
Use a layer mask when you only care about some contacts.
use Lenga\Engine\Core\Physics2D;
$groundMask = Physics2D::layerMask(3); // for example: World layer
if ($body?->isGrounded(0.5, false, $groundMask)) {
// Grounded only against the layers we consider ground
}
This keeps contact logic focused and prevents unrelated overlaps from polluting gameplay decisions.
Good Fits for Contact Queries
Contact queries are especially useful for:
- grounded movement
- ladder or climb zone checks
- melee weapons that stay active for a short window
- hazards that should damage while the player remains inside them
- editor/debug tooling that needs to inspect current overlap state
A Good Rule of Thumb
Use callbacks when you care about the exact moment contact starts or ends.
Use contact queries when you care about the current state of contact every frame.
Use casts and overlap queries when you want to probe ahead or search an area.