logo

Babylon.js Market

ShipDamageFX

fx · space-combat-sim

ShipDamageFX

2
Unlock

Install with the CLI:

bjs download ShipDamageFX

ShipDamageFX

Craters where rounds land, and wings that physically come off.

What it does

Hits and part losses have always been events; nothing drew them. ShipDamageFX: {} on the world entity gives a dogfight the two marks that make it read.

EventEffect
spaceshooter.part.destroyedthat part's meshes detach and tumble as wreckage
bullet.hita scorched puncture at the impact point on the named part
spaceshooter.player.blownapartthe player's primitives are cloned into wreckage

Wreckage inherits the dying ship's velocity, plus a random separation kick, a slight upward bias so pieces clear the hull, and per-piece tumble. Fling debris off at its own speed instead and it separates unnaturally, like a decal peeling away; a piece that keeps its orientation reads as a prop rather than as debris.

Two routing decisions are worth knowing:

  • A hit reported on part 'debris' goes to the nearest piece of wreckage, not to a hull. Debris has no entity mesh, and marking the ship it came off would put the crater where nothing was hit.
  • Asteroids and oil blobs are skipped. A rock is not a hull — shooting one throws off chips, and a scorched puncture in stone looks wrong.

Setup

The engine work ships with the component. Register it once at bootstrap, before the scene loads:

TypeScript
import { registerShipDamageFXExtension } from '@babylonjsmarket/…/ShipDamageFX/adapter/register';

const adapter = new BabylonAdapter();
registerShipDamageFXExtension(adapter);
const game = new ArcadeGame(adapter, { … });

Without it, damage leaves no marks and the System warns once.

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.

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 ShipDamageFX
    bjs download ShipDamageFX

    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
{
  "World": {
    "tags": ["world"],
    "components": {
      "ShipDamageFX": { "holeDiameter": 0.22, "maxHolesPerPart": 12 }
    }
  }
}

Props

  • spread (number, default 6) — peak random separation kick for shed pieces, units/sec.
  • lift (number, default 1.5) — upward bias, units/sec.
  • tumble (number, default 8) — peak spin, rad/sec.
  • debrisLifetimeMin / debrisLifetimeMax (number, defaults 5 / 7) — seconds before a piece is disposed.
  • holeDiameter (number, default 0.22) — base crater size; each varies up to half again.
  • maxHolesPerPart (number, default 12) — craters kept per part before the oldest is recycled.
  • seed (number, default 20260729) — fixes wreck trajectories.
  • holes (boolean, default true) — draw craters at all.
  • shedding (boolean, default true) — shed parts at all.

Events

  • listens for spaceshooter.part.destroyed, bullet.hit, spaceshooter.player.blownapart.
  • emits nothing.

Dependencies

Parts (so a hit's part name resolves to mesh suffixes) and Velocity6DOF (so wreckage inherits motion). Neither is required for the component to run — a ship with no part breakdown gets craters anywhere on its hull.

Notes

  • The player is cloned, not stripped. The player survives to respawn, so its own primitives must stay where they are; taking them is how a player ends up permanently invisible after their first death. This is also why the kill path deliberately skips the part-detach loop for the player and emits blownapart instead.
  • On a GLB ship the primitives are hidden — the model is what you see, and the primitives are the collision proxy. A shed piece has to be revealed or the wing comes off invisibly.
  • Detaching preserves world transform, so a part breaks off in place rather than snapping to the world origin.
  • Craters are capped per part, or a long firefight mints them without limit.
  • Wreckage is advanced from the ECS update, not the render loop, so the debris clock freezes with a paused world. Debris drifting on under a pause menu is a bug — which is why this System is pauseable, unlike the HUD and the explosion FX.
  • Trajectories are seeded and offset per event, so two kills in a run differ while the run itself reproduces exactly.

More like this

Bullet
Parts
SpaceShooterBullet
SpaceShooterHealth
Velocity6DOF
Asteroid
AsteroidField
CameraState6DOF
ChaseCamera6DOF
ChaseCameraTarget
FlightIntent
FreighterCar
FreighterChain
FreighterHead
GameConfig
LensFlare
NebulaSky
OilBlob
PlayerFlightInput
Renderable
ShipFlight
SpaceDust
SpaceShooterFX
SpaceShooterHUD
SpaceShooterScore
Transform6DOF
WaveDirector
Waypoint
WaypointTrack
WorldOriginAnchor

Was this page helpful?

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

↑↓ NavigateEnter SelectEsc CloseCtrl+K Open Search