AOI 兴趣区域
AOI (Area of Interest) 用于追踪实体之间的可见性关系,常用于 MMO 同步和 NPC AI 感知。
createGridAOI
Section titled “createGridAOI”function createGridAOI<T>(cellSize?: number): GridAOI<T>创建基于网格的 AOI 管理器。
参数:
cellSize- 网格单元格大小(建议为平均视野范围的 1-2 倍)
addObserver
Section titled “addObserver”添加观察者:
aoi.addObserver(player, position, { viewRange: 200, // 视野范围 observable: true // 是否可被其他观察者看到(默认 true)});
// NPC 只观察不被观察aoi.addObserver(camera, position, { viewRange: 500, observable: false});removeObserver
Section titled “removeObserver”移除观察者:
aoi.removeObserver(player);updatePosition
Section titled “updatePosition”更新位置(自动触发进入/离开事件):
aoi.updatePosition(player, newPosition);updateViewRange
Section titled “updateViewRange”更新视野范围:
// 获得增益后视野扩大aoi.updateViewRange(player, 300);getEntitiesInView
Section titled “getEntitiesInView”获取观察者视野内的所有实体:
const visible = aoi.getEntitiesInView(player);for (const entity of visible) { updateEntityForPlayer(player, entity);}getObserversOf
Section titled “getObserversOf”获取能看到指定实体的所有观察者:
const observers = aoi.getObserversOf(monster);for (const observer of observers) { notifyMonsterMoved(observer, monster);}canSee
Section titled “canSee”检查是否可见:
if (aoi.canSee(player, enemy)) { enemy.showHealthBar();}全局事件监听
Section titled “全局事件监听”aoi.addListener((event) => { switch (event.type) { case 'enter': console.log(`${event.observer} 看到了 ${event.target}`); break; case 'exit': console.log(`${event.target} 离开了 ${event.observer} 的视野`); break; }});实体特定事件监听
Section titled “实体特定事件监听”// 只监听特定玩家的视野事件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; // 观察者(谁看到了变化) target: T; // 目标(发生变化的对象) position: IVector2; // 目标位置}GetEntitiesInView- 获取视野内实体GetObserversOf- 获取观察者CanSee- 检查可见性OnEntityEnterView- 进入视野事件OnEntityExitView- 离开视野事件
在依赖注入场景中使用:
import { SpatialIndexToken, SpatialQueryToken, AOIManagerToken, createGridSpatialIndex, createGridAOI} from '@esengine/spatial';
// 注册服务services.register(SpatialIndexToken, createGridSpatialIndex(100));services.register(AOIManagerToken, createGridAOI(100));
// 获取服务const spatialIndex = services.get(SpatialIndexToken);const aoiManager = services.get(AOIManagerToken);