Raycasts, Triggers & Events
Ask the physics world questions with raycasts, and react to overlaps with sensor volumes and the onCollision script hooks.
Raycasting
A raycast fires a ray into the simulation and returns the nearest thing it hits. From a script:
ts
const hit = api.raycast(ox, oy, oz, dx, dy, dz, maxDist);
if (hit) {
// hit.point - where the ray struck (world space)
// hit.normal - the surface normal at that point
// hit.distance - distance along the ray
// hit.entity - the GameObject that was hit, or null
}ox, oy, ozis the ray origin,dx, dy, dzthe direction, andmaxDisthow far to search.- The result includes the hit point and surface normal (Awaken uses Rapier's ray-and-normal cast), the distance, and the entity that owns the collider.
hit.entityisnullwhen the ray strikes a body with no owning GameObject - most commonly the implicit ground plane. The hit is still returned; only the entity mapping is absent.- If no physics is running this session,
api.raycastreturnsnull(a clean miss), so scripts are safe to call unconditionally.
Raycasts are handy for line-of-sight checks, ground probes, shooting, and click-to-select in gameplay.
Triggers (sensors)
A trigger is a collider shape flagged as a sensor. It detects overlaps and reports them, but does not physically block anything - bodies pass straight through it. Use triggers for pickups, checkpoints, damage zones, doorways, and "player entered the room" events.
Turn on the trigger flag on a collider shape in the Inspector. A shape can be a trigger regardless of kind; the object can carry a solid shape and a trigger shape at the same time (a compound collider). To make a mesh collider a trigger, Awaken automatically builds it as a convex hull, because a hollow triangle mesh can't reliably report overlaps.
To react to a trigger, add a Script with one of the collision hooks below. Triggers and solid contacts flow through the same hooks - the difference is that a trigger doesn't stop movement.
Collision events
Under the hood, colliders are created with collision events enabled and with ActiveCollisionTypes.ALL, so even a kinematic character vs a fixed wall or static trigger generates events (Rapier would otherwise only report pairs involving a dynamic body). Each step the runner drains Rapier's begin/end contact events and folds them into a live set of currently-touching body pairs. The contacts() method maps those body pairs back to entity pairs - sourced from real engine contacts, not an AABB guess.
The script host turns that per-frame pair set into three hooks on your ScriptBehavior:
| Hook | Fires |
|---|---|
onCollisionEnter(api, other) | On the first frame this object's collider begins overlapping other (the "hit" edge). |
onCollision(api, other) | Every frame while the two colliders overlap ("stay"). |
onCollisionExit(api, other) | On the first frame they stop overlapping (the "leave" edge). Not called if other was destroyed while overlapping - there's no entity to hand back. |
Both entities in a touching pair receive the event, each told about the other. A pair is dropped the frame either entity dies. An entity with a pinned shape owns two bodies, but each entity pair is still reported only once.
Example - a pickup trigger
ts
class Coin implements ScriptBehavior {
onCollisionEnter(api: ScriptApi, other: Entity) {
if (api.world.getName(other) === "Player") {
api.state.score = (api.state.score as number ?? 0) + 1;
api.destroy(); // remove this coin (destroys the entity running this script)
}
}
}📸 Screenshot - save as img/physics-trigger-pickup.png
A coin object selected in the editor, its Collider showing a sphere shape with the trigger flag checked, and a Script component with a coin pickup behaviour attached.
Fallback when physics is off
If a Play session runs without Rapier (WASM not ready), the script host falls back to a simple bounding-box overlap test to drive the same hooks - so onCollision still fires, just with coarser AABB accuracy instead of exact contacts. When physics is running, scripts always see the real engine contacts (including sensors).
See also
- Scripting API -
raycast,onCollision, and the full behaviour surface. - Colliders & Shapes - the trigger and pinned flags.
- Character Controller - how triggers are excluded from movement.
- Events & Timers - decouple game logic from collisions.