logo

Babylon.js Market

LineOfSight

shooter

LineOfSight

Talks toEnemy
Free

Install with the CLI:

bjs download LineOfSight

LineOfSight

Reusable perception: can this entity see a tagged target, given a vision cone, max range, and occluders?

What it does

LineOfSightSystem runs on any entity that has a LineOfSight and a MeshPrimitive. It derives the entity's facing from its movement delta (mirroring visual yaw), then on a per-entity timer checks whether the tagged target sits inside the FOV cone, within range, and is reachable by at least one fanned ray that isn't blocked by other bodies or sight-blocking Obstacle walls. On a visibility change it emits lineofsight.acquired / lineofsight.lost so consumers (e.g. an enemy AI) can react — it never reads another component, so it drops onto a turret, guard, or anything. It also listens for lineofsight.debugrays.set to toggle green (clear) / red (blocked) sight-ray helpers.

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 LineOfSight

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

    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
{
  "entities": {
    "Player": {
      "tags": ["player"],
      "components": {
        "MeshPrimitive": { "primitive": "capsule", "radius": 0.5, "height": 1.6, "position": [0, 0.8, 6] }
      }
    },
    "Watcher": {
      "components": {
        "MeshPrimitive": { "primitive": "sphere", "diameter": 1.2, "position": [0, 0.6, -6] },
        "LineOfSight": {
          "targetTag": "player",
          "fov": 220,
          "range": 32,
          "rayCount": 3,
          "blockRadius": 0.6,
          "interval": 1.5
        }
      }
    }
  }
}

Props

  • targetTag (string, default "player") — tag of the entity to look for.
  • fov (number, default 220) — field-of-view cone width in degrees; >= 360 is omnidirectional.
  • range (number, default 32) — max sight distance; 0 is unbounded.
  • rayCount (number, default 3) — rays fanned across the target's width; 1 is a single centre ray.
  • blockRadius (number, default 0.6) — radius another body occupies as a ray blocker, and the fan half-width.
  • interval (number, default 1.5) — seconds between sight re-checks.

Events

  • emits lineofsight.acquired (LineOfSightEvents.ACQUIRED) with { entityId, targetId } when the entity gains sight of its target.
  • emits lineofsight.lost (LineOfSightEvents.LOST) with { entityId, targetId } when it loses sight.
  • listens for lineofsight.debugrays.set (LineOfSightInputEvents.SET_DEBUG_RAYS) with { enabled } to toggle the debug ray helpers.

Dependencies

MeshPrimitive — supplies the seer's position (and facing source) and the target's position; required by the System's query. Obstacle — walls flagged as sight-blocking become ray occluders.

Notes

  • Facing comes from the entity's movement delta and holds its last heading while stationary; with no movement yet, facing is unknown and the cone test is skipped (treated as omnidirectional).
  • Seers mutually occlude each other — every other entity with a LineOfSight acts as an occluder circle of radius blockRadius.
  • Checks are staggered: each entity's first check fires at a random offset within interval, so many seers don't all re-check on the same frame.
  • Entities tagged dying are excluded from the query.

More like this

Enemy
MeshPrimitive
Obstacle
AIGoalSeek
AIKick
AIZone
AiPilot
Animation
ArcCamera
Asteroid
BallPossession
BallPursuit
Bullet
CameraFollow
DirectionalLight
EnemySpawner
EnvironmentTexture
FreighterCar
FreighterChain
FreighterHead
GameConfig
Health
HemisphericLight
Jump
KeyboardInput
KeyboardMover
Lifetime
MachineGun
Mesh
Missile
MissileLauncher
MissionDirector
MoneyField
Movement
ObstacleField
OilBlob
Parts
Physics
PlayerInput
PlayerWalkAnimator
PokerAI
PokerAIBill
PokerAICali
PokerAIRandy
PokerAIShark
PokerAISurge
PokerAITilt
RespawnTimer
Score
Shadow
ShipLoadout
ShooterCamera
SkeletonAnimator
SpaceShooterBullet
SpaceShooterHealth
SpaceShooterScore
TwinStickShooter
WaveDirector
Waypoint
WaypointTrack

Was this page helpful?

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

↑↓ NavigateEnter SelectEsc CloseCtrl+K Open Search