UNPKG

@esengine/pathfinding

Version:

寻路系统 | Pathfinding System - A*, Grid, NavMesh

703 lines (695 loc) 22.6 kB
import { Component, EntitySystem, Entity } from '@esengine/ecs-framework'; import { S as IVector2, V as IPathPlanner, a7 as IFlowController, a0 as ILocalAvoidance, a2 as ICollisionResolver, _ as IObstacleData } from './FlowController-BztOzQsW.js'; export { ap as CollisionResolverAdapter, ab as DEFAULT_FLOW_CONTROLLER_CONFIG, ao as DEFAULT_ORCA_PARAMS, ar as FlowController, ag as GridPathfinderAdapter, a3 as ICongestionZone, a4 as IFlowAgentData, a5 as IFlowControlResult, a6 as IFlowControllerConfig, au as IGridPathfinderAdapterConfig, av as IIncrementalGridPathPlannerConfig, at as IORCAParams, ak as IncrementalGridPathPlannerAdapter, ae as NavMeshPathPlannerAdapter, am as ORCALocalAvoidanceAdapter, aa as PassPermission, ah as createAStarPlanner, aq as createDefaultCollisionResolver, as as createFlowController, aj as createHPAPlanner, al as createIncrementalAStarPlanner, ai as createJPSPlanner, af as createNavMeshPathPlanner, an as createORCAAvoidance } from './FlowController-BztOzQsW.js'; import './CollisionResolver-CSgWsegP.js'; import '@esengine/ecs-framework-math'; /** * @zh 统一导航代理组件 * @en Unified Navigation Agent Component * * @zh 算法无关的通用导航属性,配合 NavigationSystem 使用 * @en Algorithm-agnostic common navigation properties, works with NavigationSystem */ /** * @zh 导航状态 * @en Navigation state */ declare enum NavigationState { /** * @zh 空闲 * @en Idle */ Idle = "idle", /** * @zh 正在导航 * @en Navigating */ Navigating = "navigating", /** * @zh 已到达 * @en Arrived */ Arrived = "arrived", /** * @zh 路径被阻挡 * @en Path blocked */ Blocked = "blocked", /** * @zh 无法到达 * @en Unreachable */ Unreachable = "unreachable" } /** * @zh 统一导航代理组件 * @en Unified navigation agent component * * @zh 包含算法无关的通用导航属性,不包含算法特定参数 * @en Contains algorithm-agnostic common navigation properties, no algorithm-specific parameters * * @example * ```typescript * const entity = scene.createEntity('Agent'); * * // 添加导航代理组件 * const nav = entity.addComponent(new NavigationAgentComponent()); * nav.radius = 0.5; * nav.maxSpeed = 5.0; * * // 设置目标 * nav.setDestination(100, 200); * * // NavigationSystem 会自动处理: * // 1. 使用 IPathPlanner 计算全局路径 * // 2. 使用 ILocalAvoidance 进行局部避让 * // 3. 使用 ICollisionResolver 防止穿透 * ``` */ declare class NavigationAgentComponent extends Component { /** * @zh 代理半径 * @en Agent radius */ radius: number; /** * @zh 最大速度 * @en Maximum speed */ maxSpeed: number; /** * @zh 加速度(用于平滑移动) * @en Acceleration (for smooth movement) */ acceleration: number; /** * @zh 路径点到达阈值 * @en Waypoint arrival threshold */ waypointThreshold: number; /** * @zh 目标到达阈值 * @en Destination arrival threshold */ arrivalThreshold: number; /** * @zh 路径重新计算间隔(秒) * @en Path recalculation interval (seconds) */ repathInterval: number; /** * @zh 是否启用导航 * @en Whether navigation is enabled */ enabled: boolean; /** * @zh 是否自动重新计算被阻挡的路径 * @en Whether to auto repath when blocked */ autoRepath: boolean; /** * @zh 是否启用平滑转向 * @en Whether to enable smooth steering */ smoothSteering: boolean; /** * @zh 当前位置 * @en Current position */ position: IVector2; /** * @zh 当前速度 * @en Current velocity */ velocity: IVector2; /** * @zh 目标位置 * @en Destination position */ destination: IVector2 | null; /** * @zh 当前导航状态 * @en Current navigation state */ state: NavigationState; /** * @zh 当前路径 * @en Current path */ path: IVector2[]; /** * @zh 当前路径点索引 * @en Current waypoint index */ currentWaypointIndex: number; /** * @zh 上次重新计算路径的时间 * @en Last repath time */ lastRepathTime: number; /** * @zh 当前增量寻路请求 ID * @en Current incremental pathfinding request ID */ currentRequestId: number; /** * @zh 寻路进度 (0-1) * @en Pathfinding progress (0-1) */ pathProgress: number; /** * @zh 优先级(数字越小优先级越高) * @en Priority (lower number = higher priority) */ priority: number; /** * @zh 是否正在等待路径计算完成 * @en Whether waiting for path computation to complete */ isComputingPath: boolean; /** * @zh 设置位置 * @en Set position * * @param x - @zh X 坐标 @en X coordinate * @param y - @zh Y 坐标 @en Y coordinate */ setPosition(x: number, y: number): void; /** * @zh 设置目标位置 * @en Set destination * * @param x - @zh 目标 X 坐标 @en Destination X coordinate * @param y - @zh 目标 Y 坐标 @en Destination Y coordinate */ setDestination(x: number, y: number): void; /** * @zh 停止导航 * @en Stop navigation */ stop(): void; /** * @zh 获取当前路径点 * @en Get current waypoint * * @returns @zh 当前路径点,如果没有则返回 null @en Current waypoint, or null if none */ getCurrentWaypoint(): IVector2 | null; /** * @zh 获取到目标的距离 * @en Get distance to destination * * @returns @zh 到目标的距离,如果没有目标则返回 Infinity @en Distance to destination, or Infinity if no destination */ getDistanceToDestination(): number; /** * @zh 获取当前速度大小 * @en Get current speed * * @returns @zh 当前速度大小 @en Current speed magnitude */ getCurrentSpeed(): number; /** * @zh 检查是否已到达目标 * @en Check if arrived at destination * * @returns @zh 是否已到达 @en Whether arrived */ hasArrived(): boolean; /** * @zh 检查路径是否被阻挡 * @en Check if path is blocked * * @returns @zh 是否被阻挡 @en Whether blocked */ isBlocked(): boolean; /** * @zh 检查目标是否无法到达 * @en Check if destination is unreachable * * @returns @zh 是否无法到达 @en Whether unreachable */ isUnreachable(): boolean; /** * @zh 重置组件状态 * @en Reset component state */ reset(): void; /** * @zh 组件从实体移除时调用 * @en Called when component is removed from entity */ onRemovedFromEntity(): void; } /** * @zh 统一导航系统 * @en Unified Navigation System * * @zh 可插拔的导航系统,支持运行时切换寻路、避让、碰撞检测算法 * @en Pluggable navigation system, supports runtime swapping of pathfinding, avoidance, and collision detection algorithms */ /** * @zh 导航系统配置 * @en Navigation system configuration */ interface INavigationSystemConfig { /** * @zh 时间步长 * @en Time step */ timeStep?: number; /** * @zh 是否启用路径规划阶段 * @en Whether to enable path planning stage */ enablePathPlanning?: boolean; /** * @zh 是否启用流量控制阶段 * @en Whether to enable flow control stage */ enableFlowControl?: boolean; /** * @zh 是否启用局部避让阶段 * @en Whether to enable local avoidance stage */ enableLocalAvoidance?: boolean; /** * @zh 是否启用碰撞解决阶段 * @en Whether to enable collision resolution stage */ enableCollisionResolution?: boolean; /** * @zh 是否启用代理间碰撞解决 * @en Whether to enable agent-agent collision resolution */ enableAgentCollisionResolution?: boolean; /** * @zh 是否启用时间切片寻路(需要 IIncrementalPathPlanner) * @en Whether to enable time-sliced pathfinding (requires IIncrementalPathPlanner) * * @zh 启用后,寻路计算会分散到多帧执行,避免卡顿 * @en When enabled, pathfinding computation is spread across multiple frames to avoid stuttering */ enableTimeSlicing?: boolean; /** * @zh 每帧总迭代预算 * @en Total iteration budget per frame * * @zh 所有代理共享此预算,根据优先级分配 * @en All agents share this budget, allocated by priority * * @default 1000 */ iterationsBudget?: number; /** * @zh 每帧最大处理代理数 * @en Maximum agents to process per frame * * @zh 限制每帧处理的代理数量,避免过载 * @en Limits the number of agents processed per frame to avoid overload * * @default 10 */ maxAgentsPerFrame?: number; /** * @zh 每个代理每帧最大迭代数 * @en Maximum iterations per agent per frame * * @default 200 */ maxIterationsPerAgent?: number; } /** * @zh 统一导航系统 * @en Unified Navigation System * * @zh 可插拔的导航系统,处理管线:PathPlanning → LocalAvoidance → CollisionResolution * @en Pluggable navigation system, pipeline: PathPlanning → LocalAvoidance → CollisionResolution * * @example * ```typescript * import { * NavigationSystem, * NavigationAgentComponent, * createNavMeshPathPlanner, * createORCAAvoidance, * createDefaultCollisionResolver * } from '@esengine/pathfinding/ecs'; * * // 创建系统 * const navSystem = new NavigationSystem(); * * // 配置算法(可选,每个阶段都可以独立启用/禁用) * navSystem.setPathPlanner(createNavMeshPathPlanner(navMesh)); * navSystem.setLocalAvoidance(createORCAAvoidance()); * navSystem.setCollisionResolver(createDefaultCollisionResolver()); * * scene.addSystem(navSystem); * * // 添加障碍物 * navSystem.addObstacle({ vertices: [...] }); * * // 创建代理 * const agent = scene.createEntity('Agent'); * const nav = agent.addComponent(new NavigationAgentComponent()); * nav.setPosition(0, 0); * nav.setDestination(100, 100); * * // 运行时切换算法 * navSystem.setPathPlanner(createJPSPlanner(gridMap)); * navSystem.setLocalAvoidance(null); // 禁用避让 * ``` */ declare class NavigationSystem extends EntitySystem { private config; private pathPlanner; private flowController; private localAvoidance; private collisionResolver; /** * @zh 静态障碍物(墙壁、建筑等)- 由 PathPlanner 和 CollisionResolver 处理 * @en Static obstacles (walls, buildings) - handled by PathPlanner and CollisionResolver */ private staticObstacles; /** * @zh 动态障碍物(移动物体等)- 由 ORCA 和 CollisionResolver 处理 * @en Dynamic obstacles (moving objects) - handled by ORCA and CollisionResolver */ private dynamicObstacles; private currentTime; private agentEnterTimes; /** * @zh 是否为增量寻路器 * @en Whether the path planner is incremental */ private isIncrementalPlanner; /** * @zh 等待寻路的代理队列(按优先级排序) * @en Queue of agents waiting for pathfinding (sorted by priority) */ private pendingPathRequests; constructor(config?: INavigationSystemConfig); /** * @zh 设置路径规划器 * @en Set path planner * * @param planner - @zh 路径规划器,传入 null 禁用路径规划 @en Path planner, pass null to disable * * @zh 如果传入 IIncrementalPathPlanner 且启用了时间切片,会自动使用增量寻路 * @en If passing IIncrementalPathPlanner and time slicing is enabled, will automatically use incremental pathfinding * * @example * ```typescript * navSystem.setPathPlanner(createNavMeshPathPlanner(navMesh)); * navSystem.setPathPlanner(createAStarPlanner(gridMap)); * navSystem.setPathPlanner(createIncrementalAStarPlanner(gridMap)); // 支持时间切片 * navSystem.setPathPlanner(null); // 禁用 * ``` */ setPathPlanner(planner: IPathPlanner | null): void; /** * @zh 获取当前路径规划器 * @en Get current path planner */ getPathPlanner(): IPathPlanner | null; /** * @zh 设置流量控制器 * @en Set flow controller * * @param controller - @zh 流量控制器,传入 null 禁用流量控制 @en Flow controller, pass null to disable * * @example * ```typescript * navSystem.setFlowController(createFlowController()); * navSystem.setFlowController(null); // 禁用 * ``` */ setFlowController(controller: IFlowController | null): void; /** * @zh 获取当前流量控制器 * @en Get current flow controller */ getFlowController(): IFlowController | null; /** * @zh 设置局部避让算法 * @en Set local avoidance algorithm * * @param avoidance - @zh 局部避让算法,传入 null 禁用避让 @en Local avoidance, pass null to disable * * @example * ```typescript * navSystem.setLocalAvoidance(createORCAAvoidance()); * navSystem.setLocalAvoidance(null); // 禁用 * ``` */ setLocalAvoidance(avoidance: ILocalAvoidance | null): void; /** * @zh 获取当前局部避让算法 * @en Get current local avoidance algorithm */ getLocalAvoidance(): ILocalAvoidance | null; /** * @zh 设置碰撞解决器 * @en Set collision resolver * * @param resolver - @zh 碰撞解决器,传入 null 禁用碰撞解决 @en Collision resolver, pass null to disable * * @example * ```typescript * navSystem.setCollisionResolver(createDefaultCollisionResolver()); * navSystem.setCollisionResolver(null); // 禁用 * ``` */ setCollisionResolver(resolver: ICollisionResolver | null): void; /** * @zh 获取当前碰撞解决器 * @en Get current collision resolver */ getCollisionResolver(): ICollisionResolver | null; /** * @zh 添加静态障碍物(墙壁、建筑等) * @en Add static obstacle (walls, buildings, etc.) * * @zh 静态障碍物由 PathPlanner 规划路径时考虑,CollisionResolver 防止穿透 * @zh ORCA 不会处理静态障碍物,因为路径规划已经绑开了它们 * @en Static obstacles are considered by PathPlanner for routing, CollisionResolver for penetration prevention * @en ORCA does NOT process static obstacles since path planning already avoids them * * @param obstacle - @zh 障碍物数据 @en Obstacle data */ addStaticObstacle(obstacle: IObstacleData): void; /** * @zh 添加动态障碍物(移动物体、临时障碍等) * @en Add dynamic obstacle (moving objects, temporary obstacles, etc.) * * @zh 动态障碍物由 ORCA 进行局部避让,CollisionResolver 防止穿透 * @en Dynamic obstacles are handled by ORCA for local avoidance, CollisionResolver for penetration prevention * * @param obstacle - @zh 障碍物数据 @en Obstacle data */ addDynamicObstacle(obstacle: IObstacleData): void; /** * @zh 移除所有静态障碍物 * @en Remove all static obstacles */ clearStaticObstacles(): void; /** * @zh 移除所有动态障碍物 * @en Remove all dynamic obstacles */ clearDynamicObstacles(): void; /** * @zh 移除所有障碍物(静态和动态) * @en Remove all obstacles (static and dynamic) */ clearObstacles(): void; /** * @zh 获取静态障碍物列表 * @en Get static obstacles list */ getStaticObstacles(): readonly IObstacleData[]; /** * @zh 获取动态障碍物列表 * @en Get dynamic obstacles list */ getDynamicObstacles(): readonly IObstacleData[]; /** * @zh 获取所有障碍物列表(静态+动态) * @en Get all obstacles list (static + dynamic) */ getObstacles(): readonly IObstacleData[]; /** * @zh 获取所有障碍物用于碰撞检测 * @en Get all obstacles for collision detection */ private getAllObstaclesForCollision; /** * @zh 设置静态障碍物列表 * @en Set static obstacles list * * @param obstacles - @zh 障碍物列表 @en Obstacles list */ setStaticObstacles(obstacles: IObstacleData[]): void; /** * @zh 设置动态障碍物列表 * @en Set dynamic obstacles list * * @param obstacles - @zh 障碍物列表 @en Obstacles list */ setDynamicObstacles(obstacles: IObstacleData[]): void; /** * @zh 系统销毁时调用 * @en Called when system is destroyed */ protected onDestroy(): void; /** * @zh 处理实体 * @en Process entities */ protected process(entities: readonly Entity[]): void; /** * @zh 处理等待中的代理 * @en Handle waiting agent */ private handleWaitingAgent; /** * @zh 清理已移除代理的进入时间记录 * @en Cleanup enter times for removed agents */ private cleanupEnterTimes; /** * @zh 处理路径规划(同步模式) * @en Process path planning (synchronous mode) */ private processPathPlanning; /** * @zh 处理增量路径规划(时间切片模式) * @en Process incremental path planning (time slicing mode) * * @param agents - @zh 代理列表 @en Agent list * @param entityMap - @zh 实体 ID 到代理的映射 @en Entity ID to agent mapping */ private processIncrementalPathPlanning; /** * @zh 推进路径点 * @en Advance waypoint */ private advanceWaypoint; /** * @zh 计算首选速度 * @en Calculate preferred velocity */ private calculatePreferredVelocity; /** * @zh 构建代理数据 * @en Build agent data */ private buildAgentData; /** * @zh 应用避让结果 * @en Apply avoidance result */ private applyAvoidanceResult; /** * @zh 应用平滑转向 * @en Apply smooth steering */ private applySmoothSteering; /** * @zh 检查是否到达目标 * @en Check if arrived at destination */ private checkArrival; /** * @zh 解决代理间碰撞 * @en Resolve agent-agent collisions */ private resolveAgentCollisions; /** * @zh 查找有效的修正向量(不会进入障碍物) * @en Find valid correction vector (won't enter obstacles) */ private findValidCorrection; /** * @zh 查找滑动位置(当目标位置不可行走时) * @en Find slide position (when target position is not walkable) * * @zh 尝试只沿 X 轴或 Y 轴移动,实现沿墙滑动效果 * @en Try moving only along X or Y axis, achieving wall sliding effect */ private findSlidePosition; /** * @zh 检查位置是否可行走(考虑代理半径) * @en Check if position is walkable (considering agent radius) * * @zh 检查代理边界框的4个角点和中心点,确保整个代理都在可行走区域 * @en Check 4 corners and center of agent bounding box, ensure entire agent is in walkable area * * @param position - @zh 位置 @en Position * @param radius - @zh 代理半径 @en Agent radius * @param tolerance - @zh 容差比例 (0-1),用于允许轻微重叠 @en Tolerance ratio (0-1), allows slight overlap */ private isPositionWalkable; } /** * @zh ORCA 算法配置组件 * @en ORCA Algorithm Configuration Component * * @zh 可选组件,仅当使用 ORCA 避让算法时需要,用于覆盖默认 ORCA 参数 * @en Optional component, only needed when using ORCA avoidance, to override default ORCA parameters */ /** * @zh ORCA 算法配置组件 * @en ORCA algorithm configuration component * * @zh 可选组件,附加到代理实体上以覆盖默认 ORCA 参数 * @en Optional component, attach to agent entities to override default ORCA parameters * * @example * ```typescript * const entity = scene.createEntity('Agent'); * * // 添加导航代理 * entity.addComponent(new NavigationAgentComponent()); * * // 可选:添加 ORCA 配置以自定义参数 * const orcaConfig = entity.addComponent(new ORCAConfigComponent()); * orcaConfig.timeHorizon = 3.0; // 更长的预测时间 * orcaConfig.neighborDist = 20.0; // 更大的邻居检测范围 * ``` */ declare class ORCAConfigComponent extends Component { /** * @zh 邻居检测距离 * @en Neighbor detection distance * * @zh 代理检测邻居的最大距离,更大的值意味着更早开始避让但也更消耗性能 * @en Maximum distance for detecting neighbors, larger value means earlier avoidance but more performance cost */ neighborDist: number; /** * @zh 最大邻居数量 * @en Maximum number of neighbors * * @zh 计算避让时考虑的最大邻居数量,更多邻居意味着更精确但也更消耗性能 * @en Maximum neighbors considered for avoidance, more neighbors means more accurate but slower */ maxNeighbors: number; /** * @zh 代理避让时间视野 * @en Time horizon for agent avoidance * * @zh 预测其他代理未来位置的时间范围,更长意味着更平滑但可能过度避让 * @en Time range for predicting other agents' future positions, longer means smoother but may over-avoid */ timeHorizon: number; /** * @zh 障碍物避让时间视野 * @en Time horizon for obstacle avoidance * * @zh 预测与障碍物碰撞的时间范围,通常比代理视野短 * @en Time range for predicting obstacle collisions, usually shorter than agent horizon */ timeHorizonObst: number; } export { IFlowController, type INavigationSystemConfig, NavigationAgentComponent, NavigationState, NavigationSystem, ORCAConfigComponent };