logo

Babylon.js Market

SpaceShooterBullet

shooter · space-combat-sim

SpaceShooterBullet

Talks toEnemy
1
Unlock

Install with the CLI:

bjs download SpaceShooterBullet

SpaceShooterBullet

One machine-gun round in flight for a 6-DOF dogfighter, and the per-part collision that turns a hit into damage, debris, and death. The space-shooter projectile — not the canonical physics Bullet.

What it does

SpaceShooterBulletComponent is pure bookkeeping: ownerEntityId (so a bullet can't hit the ship that fired it), damage, and an optional swept-sphere radius (guns pass 0 for a point sweep; a bigger projectile inflates the hitbox so a graze still registers). Motion is a plain Velocity6DOF.

SpaceShooterBulletSystem (priority 52) runs the collision each frame over every live bullet:

  1. Reconstruct the bullet's previous-frame position from velocity · dt and sample points along the swept segment (so a fast round can't tunnel through a thin part).
  2. For each ship, rotate those sample points into the ship's LOCAL frame using its quaternion basis, then AABB-test them against the Parts boxes — first match wins (parts are ordered small→big so the cockpit reads over the body).
  3. On a hit: subtract damage from that part's HP, emit bullet.hit, and sync the aggregate SpaceShooterHealth from Parts.totalHp() for the HUD. If the part reaches 0 it detaches (wingman.part.destroyed) and sheds a shootable debris hitbox; a critical part (body/cockpit) routes through the shared destroyShip path (full death), a non-critical one just puffs a small wingman.explosion and the ship flies on.

It also sweeps bullets against floating debris hitboxes (a sphere test), and culls the player's own tracers the instant they drift behind the player's forward vector — so a looping player never flies back into their own 15-second-lived stream.

Use it in a scene

Bullets are pooled, not hand-placed — declare a bullet Pool blueprint and let the gun fill it:

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

    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
{
  "Bullets": {
    "components": {
      "Pool": { "size": 256 },
      "Transform6DOF": {},
      "Velocity6DOF": {},
      "SpaceShooterBullet": { "damage": 1 },
      "Renderable": { "shape": "bullet" },
      "Lifetime": { "remaining": 15 }
    }
  }
}

Because the blueprint carries the SpaceShooterBullet key, SpaceShooterBulletSystem registers automatically — the pooled rounds are swept for collisions with no extra wiring. MachineGun acquires a slot with world.acquire("Bullets") and sets the muzzle pose + ownerEntityId on it.

Props

  • ownerEntityId (string, default "") — the entity that fired the round; skipped as a collision target so a ship can't shoot itself.
  • damage (number, default 1) — HP removed from the part (or debris) it strikes.
  • radius (number, default 0) — swept-sphere radius. 0 is a point sweep (guns); a larger value inflates every part AABB so a near-miss still counts.

Events

  • Emits bullet.hit (BulletEvents.HIT, the shared arcade gun-hit) on every registered strike — { shooterId, targetId, part, partHp, x, y, z }. The observer hook for score/FX.
  • Emits wingman.part.destroyed (PartsEvents.DESTROYED) when a part sheds, and wingman.explosion (SpaceShooterHealthEvents.EXPLOSION) for a non-critical part burst.
  • Calls destroyShip inline on a critical-part kill (which emits the death events) rather than routing the kill through an event.
  • Listens for nothing — the collision is driven off its [SpaceShooterBullet, Transform6DOF] query.

Dependencies

  • Transform6DOF / Velocity6DOF — the round's pose + motion, and the swept-segment reconstruction.
  • Parts — the per-box hull it AABB-tests and damages; totalHp() feeds the HUD aggregate.
  • SpaceShooterHealth — the shared destroyShip kill path + spawnDebrisHitbox a critical kill routes through, and the SpaceShooterHealth component debris carries so wreckage stays shootable.

Notes

  • Distinct from Bullet. The canonical Bullet is a MeshPrimitive + Obstacle physics round on a flat arena; this is the 6-DOF space projectile with per-part quaternion-local AABB collision. Same word, two components — the subgenre prefix disambiguates.
  • removeEntity releases the pool slot. Bullets live on a Pool blueprint, so a spent or hitting round is parked back for reuse rather than destroyed.
  • Kills are decided per-part, not off the aggregate HP. The SpaceShooterHealth number is a HUD mirror of Parts.totalHp(); the death trigger is a critical part reaching 0.

More like this

Enemy
Parts
SpaceShooterHealth
Transform6DOF
Velocity6DOF
AiPilot
Animation
ArcCamera
Asteroid
Bullet
CameraFollow
ChaseCamera6DOF
ChaseCameraTarget
DirectionalLight
EnemySpawner
EnvironmentTexture
FlightIntent
FreighterCar
FreighterChain
FreighterHead
GameConfig
Health
HemisphericLight
Jump
KeyboardInput
KeyboardMover
Lifetime
LineOfSight
MachineGun
Mesh
MeshPrimitive
Missile
MissileLauncher
MissionDirector
MoneyField
Movement
Obstacle
ObstacleField
OilBlob
Physics
PlayerFlightInput
PlayerInput
PlayerWalkAnimator
RespawnTimer
Score
Shadow
ShipFlight
ShipLoadout
ShooterCamera
SkeletonAnimator
SpaceDust
SpaceShooterScore
TwinStickShooter
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