Skip to content

AOI (Area of Interest)

AOI (Area of Interest) tracks visibility relationships between entities, commonly used for MMO synchronization and NPC AI perception.

function createGridAOI<T>(cellSize?: number): GridAOI<T>

Creates a grid-based AOI manager.

Parameters:

  • cellSize - Grid cell size (recommended: 1-2x average view range)

Add an observer:

aoi.addObserver(player, position, {
viewRange: 200, // View range
observable: true // Can be seen by other observers (default true)
});
// NPC that only observes but cannot be observed
aoi.addObserver(camera, position, {
viewRange: 500,
observable: false
});

Remove an observer:

aoi.removeObserver(player);

Update position (automatically triggers enter/exit events):

aoi.updatePosition(player, newPosition);

Update view range:

// View range expanded after buff
aoi.updateViewRange(player, 300);

Get all entities within an observer’s view:

const visible = aoi.getEntitiesInView(player);
for (const entity of visible) {
updateEntityForPlayer(player, entity);
}

Get all observers who can see a specific entity:

const observers = aoi.getObserversOf(monster);
for (const observer of observers) {
notifyMonsterMoved(observer, monster);
}

Check visibility:

if (aoi.canSee(player, enemy)) {
enemy.showHealthBar();
}
aoi.addListener((event) => {
switch (event.type) {
case 'enter':
console.log(`${event.observer} sees ${event.target}`);
break;
case 'exit':
console.log(`${event.target} left ${event.observer}'s view`);
break;
}
});
// Only listen to a specific player's view events
aoi.addEntityListener(player, (event) => {
if (event.type === 'enter') {
sendToClient(player, 'entity_enter', event.target);
} else if (event.type === 'exit') {
sendToClient(player, 'entity_exit', event.target);
}
});
interface IAOIEvent<T> {
type: 'enter' | 'exit' | 'update';
observer: T; // Observer (who saw the change)
target: T; // Target (object that changed)
position: IVector2; // Target position
}
  • GetEntitiesInView - Get entities in view
  • GetObserversOf - Get observers
  • CanSee - Check visibility
  • OnEntityEnterView - Enter view event
  • OnEntityExitView - Exit view event

For dependency injection scenarios:

import {
SpatialIndexToken,
SpatialQueryToken,
AOIManagerToken,
createGridSpatialIndex,
createGridAOI
} from '@esengine/spatial';
// Register services
services.register(SpatialIndexToken, createGridSpatialIndex(100));
services.register(AOIManagerToken, createGridAOI(100));
// Get services
const spatialIndex = services.get(SpatialIndexToken);
const aoiManager = services.get(AOIManagerToken);