logo

Babylon.js Market

BallReset

gameplay

BallReset

1
Unlock

Install with the CLI:

bjs download BallReset

BallReset

Teleports a ball back to a safe spawn point when it falls out of play, scores, or is asked to.

What it does

BallResetSystem samples each ball's world position through the renderer adapter every frame and feeds it to a pure deterministic core (BallReset.core). The core fires a reset for any of: an out-of-bounds violation (below minY, above maxY, or past the boundaryX / boundaryZ edge — the new position is clamped back just inside the field by edgeInset), a fall into an optional center-hole trap (which respawns at a deterministic random point on a circle of radius edgeSpawnRadius, seeded by seed), a scored goal, or an explicit external request. A cooldown blocks back-to-back resets so a ball resting inside a trigger volume can't double-fire. The System listens on the EventBus for ballReset.request (optionally scoped to one entityId, with an optional override position), goal.scored (so a Goal mechanic respawns the ball with no extra wiring), and meshprimitive.created to resolve the mesh handle. On the frame it teleports the ball it calls setMeshPosition on the handle and emits ballReset.performed for HUDs, counters, or VFX to react to.

Use it in a scene

A scene is just data — a list of entities, each with its components. At startup the SceneLoader turns this JSON into a live world; edit the file and reload to rebuild it.

Fastest path

bjs download scene BallReset

Pulls this exact scene into your project and runs it — no copy-paste. Add --all to grab the components and assets it needs too.

Or build it from scratch with the bjs CLI:

  1. 1Scaffold a project
    npm create @babylonjsmarket/arcade@latest my-game

    World, renderer, and dev server — ready to run.

  2. 2Install dependencies
    cd my-game && npm install
  3. 3Add BallReset
    bjs download BallReset

    Copies its source into src/ so the scene resolves.

    First time? Run bjs login once.

  4. 4Paste the scene into src/scenes/arcade-room.ts and run
    npm run dev

    SceneLoader builds the world from the JSON; reload to rebuild.

JSON
{
  "Ball": {
    "tags": ["ball"],
    "components": {
      "MeshPrimitive": {
        "primitive": "sphere", "diameter": 1, "position": [0, 1, 0],
        "material": { "diffuseColor": [0.95, 0.9, 0.4] }
      },
      "BallReset": {
        "resetY": 1, "minY": -5, "boundaryX": 35, "boundaryZ": 35,
        "edgeInset": 2, "cooldown": 0.5, "defaultPosition": [0, 1, 0]
      }
    }
  }
}

Props

  • resetY (number, default 1) — Y the ball is teleported to on a bounds reset.
  • minY (number, default -5) — reset fires if the ball drops below this Y.
  • maxY (number, default 20) — reset fires if the ball rises above this Y.
  • boundaryX (number, default 35) — reset fires if |x| exceeds this.
  • boundaryZ (number, default 35) — reset fires if |z| exceeds this.
  • edgeInset (number, default 2) — horizontal inset from the boundary; the reset position lands this far inside the edge rather than on the line.
  • centerHoleRadius (number, default 0) — radius of an optional center-hole trap; 0 disables the check.
  • centerHolePosition ([x,y,z], default [0, 0, 0]) — world-space center of the hole.
  • centerHoleMaxY (number, default 1) — Y at or under which a ball inside the hole radius counts as fallen in.
  • edgeSpawnRadius (number, default 10) — radius of the random spawn circle used after a center-hole fall.
  • cooldown (number, default 0.5) — seconds the core blocks another reset after one fires.
  • defaultPosition ([x,y,z], default [0, 1, 0]) — fallback reset position used when the core fires without a sampled ball position (e.g. a bare ballReset.request).
  • seed (number, default 1) — seed for the deterministic random-edge spawn PRNG.

Events

  • Emits ballReset.performed (BallResetEvents.PERFORMED) on the frame the ball is teleported, with { entityId, position, reason, totalResets }. reason is one of request | goal | minY | maxY | boundaryX | boundaryZ | centerHole.
  • Listens for ballReset.request (BallResetInputEvents.REQUEST) — { entityId?, position? }. A missing entityId resets every BallReset entity; position overrides defaultPosition.
  • Listens for goal.scored (BallResetInputEvents.GOAL_SCORED) — { triggerEntityId? }. The matching ball is queued for a reset; triggerEntityId targets one ball, otherwise all are queued.

Dependencies

MeshPrimitive — supplies the ball mesh whose world position the System samples and teleports each frame. The handle is resolved from meshprimitive.created and from a sweep of existing entities at init, so attach order doesn't matter.

Notes

  • The System only teleports — it does not zero physics velocity, because the renderer adapter has no physics surface. With physics on, a teleported ball can carry its old velocity; pair this with a physics sync step that honors the post-reset position.
  • A goal.scored tick is queued, not fired immediately, so a celebrate animation can play while the cooldown runs out before the ball snaps back.
  • The center-hole check has priority over the bounds checks, so a pit in the middle of the field wins even if the ball is also outside a boundary that frame.
  • Same seed gives the same sequence of random edge spawns — useful for replays and tests.

More like this

Goal
MeshPrimitive
AIGoalSeek
AIKick
AIZone
BallPossession
BallPursuit
GameConfig
MissionDirector
PlayerInputBridge
PokerBetting
PokerHandEval
PokerMultiplayer
PokerTableDirector
RespawnTimer
Scoreboard
SoccerDirector
TurnPacer
WaveDirector

Was this page helpful?

We read every note — tell us what's working and what isn't.

↑↓ NavigateEnter SelectEsc CloseCtrl+K Open Search