FFCPathingComponent.h
Source/FlowFieldCanvas/Public/FFCPathingComponent.h
概述 Overview
给 Actor 提供流场跟随与个体寻路移动能力的 UActorComponent(BlueprintSpawnableComponent)。两种移动模式:FlowField——每帧查询 QueryNavigationAdvanced 跟随流场方向直至目标;Path——用 NavMesh(FindPathNavMesh)或 Grid A*(FindPathAStar)算出路径后逐段跟随,可追踪移动目标 Actor 并自动重规划。移动直接 SetActorLocation(不做物理/碰撞),由异步蓝图节点(FFCPathingAsyncAction.h)驱动,成功/失败经 OnSuccess / OnFailed 广播。
A UActorComponent (BlueprintSpawnableComponent) giving actors flow-field following and individual pathfinding movement. Two movement modes: FlowField — queries QueryNavigationAdvanced each frame to follow the field toward its goal; Path — computes a path via NavMesh (FindPathNavMesh) or Grid A* (FindPathAStar) and follows it segment by segment, optionally tracking a moving goal actor with automatic replanning. Movement is applied directly via SetActorLocation (no physics/collision); driven by async blueprint nodes (FFCPathingAsyncAction.h) with success/failure broadcast through OnSuccess / OnFailed.
EFFCMovementState UENUM
组件的移动状态机。
The component's movement state machine.
| 值 Value | 说明 Description |
|---|---|
Idle | 静止:不 tick 移动逻辑。Idle: no movement logic runs. |
FlowField | 跟随流场方向。Following the flow field. |
Path | 跟随个体寻路路径。Following an individual path. |
EFFCPathRequestResult UENUM
寻路请求的启动结果。
Result of a path request.
| 值 Value | 说明 Description |
|---|---|
Success | 路径已计算并开始跟随。Path computed and following started. |
Failed | 无有效路径或其它失败(如无 Owner、路径点不足)。No valid path or other failure (e.g. no owner, fewer than 2 path points). |
NoFlowField | 未设置有效的流场引用。No valid flow field reference set. |
AlreadyAtGoal | 已在目标接受半径内,无需移动。Already within the goal acceptance radius; no movement needed. |
Timeout | 枚举已定义;当前实现中超时走 OnFailed 广播路径,未作为返回值使用。Enum defined; in the current implementation timeouts go through the OnFailed broadcast and are not returned. |
继承 Inheritance
公开方法 Public Methods
启用组件 Tick,但 bStartWithTickEnabled = false——仅在开始移动后(StartFlowFieldFollowing / StartPathFollowing 成功)才启用,静止时零开销。
Enables the component tick but with bStartWithTickEnabled = false — ticking is enabled only after movement starts (a successful StartFlowFieldFollowing / StartPathFollowing), so idle components cost nothing.
Input
无参数。
No parameters.
Output
无返回值。副作用:设置 Tick 默认关闭。
No return value. Side effect: tick disabled by default.
每帧驱动:① Idle 直接返回;② 超时检查——剩余时间归零则先拷贝 OnFailed 委托、StopMovement(清空绑定)、再广播失败;③ 到达检查——HasReachedGoal() 为真则拷贝 OnSuccess、停止、广播成功;④ 按状态分发到 TickFlowFieldFollowing / TickPathFollowing;⑤ 有方向时 ApplyMovement;⑥ 开启调试时 DrawDebug()。注意广播前先拷贝委托并停止——StopMovement 会清空委托绑定。
Per-frame driver: ① returns immediately when Idle; ② timeout check — when the remaining time hits zero, copies the OnFailed delegate, calls StopMovement (clearing bindings), then broadcasts failure; ③ goal check — when HasReachedGoal() is true, copies OnSuccess, stops, and broadcasts success; ④ dispatches by state to TickFlowFieldFollowing / TickPathFollowing; ⑤ applies movement when a direction exists; ⑥ calls DrawDebug() when debug is enabled. Note the delegate is copied before broadcasting and movement is stopped first — StopMovement clears delegate bindings.
Input
| 参数 Param | 类型 Type | 说明 Description |
|---|---|---|
DeltaTime | float | 本帧时间步长(秒),用于超时倒计时与移动位移。Frame delta time in seconds; used for timeout countdown and movement displacement. |
TickType | ELevelTick | 引擎 tick 类型,透传给父类。Engine tick type; forwarded to the parent. |
ThisTickFunction | FActorComponentTickFunction* | 本组件的 tick 函数,透传给父类。This component's tick function; forwarded to the parent. |
Output
无返回值。副作用:移动位移、超时/到达时停止并广播成功或失败委托。
No return value. Side effects: movement displacement; on timeout/arrival, stops and broadcasts the success or failure delegate.
设置用于导航的流场弱引用,覆盖之前分配的流场。
Sets the flow field weak reference to use for navigation, overriding any previously assigned field.
Input
| 参数 Param | 类型 Type | 说明 Description |
|---|---|---|
InFlowField | AFlowField* | 流场 Actor 指针。Pointer to the flow field actor. |
Output
无返回值。副作用:写入 FlowField 弱引用。
No return value. Side effect: writes the FlowField weak reference.
返回当前流场指针(弱引用解析,可能为 nullptr)。
Returns the current flow field pointer (resolved from the weak reference; may be nullptr).
Input
无参数。
No parameters.
Output
返回流场指针;未设置或已销毁时为 nullptr。
Returns the flow field pointer, or nullptr when unset or destroyed.
开始流场跟随模式。流程:① 流场或 Owner 无效 → 广播 OnFailed;② QueryNavigationAdvanced(OwnerLocation, SearchRadius) 查询结果无效 → 广播失败;③ 已在目标(bIsAtGoal 或二维距离 ≤ AcceptanceRadius)→ 广播 OnSuccess;④ 否则进入 FlowField 状态、记录目标与初始方向、按 Timeout > 0 设置超时、启用 Tick。
Starts flow field following mode. Flow: ① invalid flow field or owner → broadcast OnFailed; ② invalid QueryNavigationAdvanced(OwnerLocation, SearchRadius) result → broadcast failure; ③ already at goal (bIsAtGoal or 2D distance ≤ AcceptanceRadius) → broadcast OnSuccess; ④ otherwise enter the FlowField state, store the goal and initial direction, arm the timeout when Timeout > 0, and enable ticking.
Input
| 参数 Param | 类型 Type | 说明 Description |
|---|---|---|
Timeout | float | 超时秒数,0 = 无超时。Timeout in seconds; 0 = no timeout. |
Output
无返回值。副作用:进入 FlowField 状态并启用 Tick;失败/已在目标时立即广播对应委托。
No return value. Side effects: enters the FlowField state and enables ticking; broadcasts the matching delegate immediately on failure or already-at-goal.
开始向固定位置做个体寻路。流程:① 无流场 → NoFlowField;② 无 Owner → Failed;③ 已在目标半径内 → AlreadyAtGoal;④ 按 bUseNavMeshPathfinding 选 FindPathNavMesh 或 FindPathAStar(惰性创建共享 FFlowfieldScratchContext),无路径或路径点不足 → Failed;⑤ 进入 Path 状态,用 GetSteeringDirection 计算初始转向,设置超时,清空目标 Actor,记录 LastPlannedGoalLocation,启用 Tick → Success。
Starts individual pathfinding to a fixed location. Flow: ① no flow field → NoFlowField; ② no owner → Failed; ③ already within the acceptance radius → AlreadyAtGoal; ④ picks FindPathNavMesh or FindPathAStar per bUseNavMeshPathfinding (lazily creating a shared FFlowfieldScratchContext); no path or fewer than 2 points → Failed; ⑤ enters the Path state, computes the initial steering via GetSteeringDirection, arms the timeout, clears the goal actor, records LastPlannedGoalLocation, and enables ticking → Success.
Input
| 参数 Param | 类型 Type | 说明 Description |
|---|---|---|
Goal | const FVector& | 目标世界位置。Goal world location. |
Timeout | float | 超时秒数,0 = 无超时。Timeout in seconds; 0 = no timeout. |
Output
返回 EFFCPathRequestResult(Success / Failed / NoFlowField / AlreadyAtGoal)。副作用:成功时进入 Path 状态并启用 Tick。
Returns an EFFCPathRequestResult (Success / Failed / NoFlowField / AlreadyAtGoal). Side effects: on success, enters the Path state and enables ticking.
向目标 Actor 做个体寻路:先以 Actor 当前位置调用 StartPathFollowing,成功后把 GoalActor 记为目标并记录初始规划位置——之后目标移动超过 GoalActorReplanThreshold 时自动重规划。
Pathfinding to a goal actor: first calls StartPathFollowing with the actor's current location; on success, stores the actor as GoalActor and records the initial planned location — subsequent goal movement beyond GoalActorReplanThreshold triggers automatic replanning.
Input
| 参数 Param | 类型 Type | 说明 Description |
|---|---|---|
InGoalActor | AActor* | 要追踪的目标 Actor;为 nullptr 时返回 Failed。Goal actor to track; nullptr returns Failed. |
Timeout | float | 超时秒数,透传给 StartPathFollowing。Timeout in seconds; forwarded to StartPathFollowing. |
Output
返回 EFFCPathRequestResult;成功时副作用为记录 GoalActor 与 LastPlannedGoalLocation。
Returns an EFFCPathRequestResult; on success, records GoalActor and LastPlannedGoalLocation.
停止一切移动并复位状态:状态置 Idle、方向清零、路径清空、超时清除、目标 Actor 复位,清空 OnSuccess / OnFailed 的全部绑定,并关闭组件 Tick。
Stops all movement and resets state: state to Idle, direction zeroed, path cleared, timeout cleared, goal actor reset, all OnSuccess / OnFailed bindings cleared, and the component tick disabled.
Input
无参数。
No parameters.
Output
无返回值。副作用:状态与全部移动数据复位,委托绑定清空,Tick 关闭。
No return value. Side effects: state and all movement data reset, delegate bindings cleared, tick disabled.
是否处于移动状态(状态 != Idle)。
Whether the component is moving (state != Idle).
Input
无参数。
No parameters.
Output
返回 true = 正在移动。
Returns true when moving.
返回当前移动状态。
Returns the current movement state.
Input
无参数。
No parameters.
Output
返回 EFFCMovementState。
Returns EFFCMovementState.
返回当前转向方向(归一化二维方向);空闲(StopMovement 复位后)为零向量。
Returns the current steering direction (normalized 2D); zero when idle (reset by StopMovement).
Input
无参数。
No parameters.
Output
返回当前方向向量。
Returns the current direction vector.
返回到当前目标(可能为目标 Actor 当前位)的二维距离。Owner 已销毁时返回 -1.0f 表示无效。
Returns the 2D distance to the current goal (which may be the goal actor's current location). Returns -1.0f when the owner is gone, signaling invalid.
Input
无参数。
No parameters.
Output
返回二维距离;Owner 无效时为 -1.0f。
Returns the 2D distance; -1.0f when the owner is invalid.
返回当前记录的目标位置(FlowField 模式下每帧从导航结果更新;Path 模式下为路径目标,追踪 Actor 时随 Actor 更新)。
Returns the current recorded goal location (updated each frame from the navigation result in FlowField mode; the path goal in Path mode, refreshed from the tracked actor when following one).
Input
无参数。
No parameters.
Output
返回目标位置向量。
Returns the goal location vector.
FlowField 模式每帧逻辑:流场或 Owner 失效 → 停止并广播失败;否则 QueryNavigationAdvanced(OwnerLocation, SearchRadius) 查询:结果无效(丢失流场)→ 停止并广播失败;有效则更新 GoalLocation 与 CurrentDirection(流场目标可动态变化)。
Per-frame logic for FlowField mode: invalid flow field or owner → stop and broadcast failure; otherwise QueryNavigationAdvanced(OwnerLocation, SearchRadius) — an invalid result (lost the flow field) stops and broadcasts failure; a valid one updates GoalLocation and CurrentDirection (flow field goals can change dynamically).
Input
| 参数 Param | 类型 Type | 说明 Description |
|---|---|---|
DeltaTime | float | 本帧时间步长(秒),当前未使用。Frame delta time in seconds; currently unused. |
Output
无返回值。副作用:更新目标与方向;失效时停止并广播失败。
No return value. Side effects: updates goal and direction; on failure, stops and broadcasts failure.
Path 模式每帧逻辑:① Owner 无效或路径点不足 → 停止并广播失败;② 追踪 Actor 时更新目标并检查 ShouldReplanPath(),需要则 ReplanPath();③ 用 GetSteeringDirection 更新转向与路径索引;④ 无有效路径时直接指向目标(GetSafeNormal2D)。
Per-frame logic for Path mode: ① invalid owner or too few path points → stop and broadcast failure; ② when tracking an actor, updates the goal and checks ShouldReplanPath(), replanning via ReplanPath() when needed; ③ updates steering and the path index via GetSteeringDirection; ④ with no valid path, points straight at the goal (GetSafeNormal2D).
Input
| 参数 Param | 类型 Type | 说明 Description |
|---|---|---|
DeltaTime | float | 本帧时间步长(秒),当前未使用。Frame delta time in seconds; currently unused. |
Output
无返回值。副作用:更新转向方向、推进路径索引,必要时重规划路径。
No return value. Side effects: updates the steering direction, advances the path index, and replans when necessary.
判断是否到达目标:Owner 无效返回 false;追踪 Actor 时用其当前位,否则用记录目标;二维距离 ≤ AcceptanceRadius 即为到达。
Determines whether the goal is reached: false when the owner is invalid; uses the goal actor's current location when tracking one, otherwise the recorded goal; reached when the 2D distance ≤ AcceptanceRadius.
Input
无参数。
No parameters.
Output
返回是否已到达目标。
Returns whether the goal has been reached.
应用移动:位移 = Direction * MoveSpeed * DeltaTime,直接 Owner->SetActorLocation(sweep 开启)。源码注释说明这是简化实现——需要物理/碰撞的复杂移动应由使用者用方向驱动自己的移动系统(如 CharacterMovementComponent)。
Applies movement: displacement = Direction * MoveSpeed * DeltaTime, applied directly via Owner->SetActorLocation (sweep on). The source comment notes this is a simple implementation — for complex movement (physics, collision), users should drive their own movement system (e.g. CharacterMovementComponent) with the direction.
Input
| 参数 Param | 类型 Type | 说明 Description |
|---|---|---|
Direction | const FVector& | 移动方向(预期已归一化)。Movement direction (expected normalized). |
DeltaTime | float | 本帧时间步长(秒)。Frame delta time in seconds. |
Output
无返回值。副作用:修改 Owner 的 Actor 位置。
No return value. Side effect: modifies the owner's actor location.
判断是否需要重规划:未追踪 Actor 时恒 false;追踪时目标 Actor 当前位与 LastPlannedGoalLocation 的二维距离超过 GoalActorReplanThreshold 即为需要。
Whether the path needs replanning: always false when not tracking an actor; when tracking, true when the goal actor's current location moved more than GoalActorReplanThreshold (2D) from LastPlannedGoalLocation.
Input
无参数。
No parameters.
Output
返回是否需要重规划。
Returns whether replanning is needed.
重规划到当前目标(追踪 Actor 时用其当前位,否则用记录目标):重新执行 NavMesh / Grid A* 寻路;成功(路径 ≥ 2 点)则更新目标、LastPlannedGoalLocation、重置路径索引并返回 true,否则返回 false 保持旧路径。
Replans to the current goal (the goal actor's current location when tracking one, otherwise the recorded goal): re-runs NavMesh / Grid A* pathfinding; on success (≥ 2 path points) updates the goal, LastPlannedGoalLocation, resets the path index, and returns true; otherwise returns false and keeps the old path.
Input
无参数。
No parameters.
Output
返回是否重规划成功。
Returns whether the replan succeeded.
调试可视化:绿色球(目标 + 接受半径)、黄色圆(Owner 接受半径)、青色箭头(当前方向)、白色虚线(到目标的连线);Path 模式下绘制路径线段(已完成=蓝 / 当前段=橙 / 未到达=红)、路径点(当前目标点半径 = PathRadius、品红)、当前目标点半径圆,以及包含状态、距离、超时信息的调试文本。
Debug visualization: green sphere (goal + acceptance radius), yellow circle (owner's acceptance radius), cyan arrow (current direction), white dashed line (to the goal); in Path mode also path segments (completed = blue / current = orange / upcoming = red), waypoints (current target sized PathRadius, magenta), the current target's radius circle, and a debug text with state, distance, and timeout info.
Input
无参数。
No parameters.
Output
无返回值。副作用:绘制调试形状(世界/场景无效时不绘制)。
No return value. Side effects: draws debug shapes (skipped when the world/owner is invalid).
成员变量 Members
| 名称 Name | 类型 Type | 默认值 | 说明 Description |
|---|---|---|---|
MoveSpeed | float | 600.0f | 移动速度(cm/s)。Movement speed in cm/s. |
AcceptanceRadius | float | 50.0f | 判定到达目标的距离阈值。Distance at which the goal is considered reached. |
PathRadius | float | 100.0f | 判定到达路径途经点的距离阈值(中间点用,终点用 AcceptanceRadius)。Distance at which path waypoints are considered reached (intermediate points; the final point uses AcceptanceRadius). |
SearchRadius | float | 0.0f | 流场插值搜索半径(0 = 单格查询,>0 = 半径内加权平均)。Flow field interpolation search radius (0 = single cell lookup, >0 = weighted average). |
LookAheadDistance | float | 200.0f | 路径转向的预瞄距离(传给 GetSteeringDirection,当前实现未使用)。Look-ahead distance for path steering (passed to GetSteeringDirection; unused in the current implementation). |
bUseNavMeshPathfinding | bool | true | true = NavMesh 寻路(FindPathNavMesh);false = Grid A*(FindPathAStar)。true = NavMesh pathfinding (FindPathNavMesh); false = Grid A* (FindPathAStar). |
AgentRadius | float | 50.0f | Grid A* 寻路排障用的 agent 半径(仅 !bUseNavMeshPathfinding 时可编辑)。Agent radius for Grid A* pathfinding exclusion (editable only when !bUseNavMeshPathfinding). |
AgentHalfHeight | float | 90.0f | Grid A* 寻路用的 agent 半高(仅 !bUseNavMeshPathfinding 时可编辑)。Agent half-height for Grid A* pathfinding (editable only when !bUseNavMeshPathfinding). |
GoalActorReplanThreshold | float | 200.0f | 目标 Actor 移动超过该距离(二维)后触发路径重规划。Path replan triggers when the goal actor moves beyond this distance (2D). |
bDrawDebug | bool | false | 是否绘制调试形状(路径、方向、目标)。Whether to draw debug shapes (path, direction, goal). |
OnSuccess | FFFCPathingResultDelegate | — | 到达目标时广播(UPROPERTY,供异步蓝图节点绑定)。Broadcast when the goal is reached (UPROPERTY, for async blueprint node binding). |
OnFailed | FFFCPathingResultDelegate | — | 移动失败(超时、无效路径等)时广播。Broadcast on movement failure (timeout, invalid path, etc.). |
FlowField | TWeakObjectPtr<AFlowField> (private) | — | 当前流场弱引用。Current flow field weak reference. |
MovementState | EFFCMovementState (private) | Idle | 当前移动状态。Current movement state. |
CurrentDirection | FVector (private) | ZeroVector | 当前转向方向。Current steering direction. |
GoalLocation | FVector (private) | ZeroVector | 当前目标位置。Current goal location. |
GoalActor | TWeakObjectPtr<AActor> (private) | — | 追踪的目标 Actor(若有)。Goal actor to track (if any). |
LastPlannedGoalLocation | FVector (private) | ZeroVector | 上次规划路径时的目标位置(用于目标移动检测)。Last location the path was planned to (for goal movement detection). |
PathPoints | TArray<FVector> (private) | 空 | 个体寻路的路径点。Path points for individual pathfinding. |
CurrentPathIndex | int32 (private) | 0 | 当前路径索引。Current index in the path. |
TimeoutRemaining | float (private) | 0.0f | 剩余超时时间。Remaining timeout time. |
bHasTimeout | bool (private) | false | 是否启用超时。Whether a timeout is armed. |
ScratchContext | TSharedPtr<FFlowfieldScratchContext> (private) | — | A* 寻路共享的暂存上下文(复用以避免分配)。Shared scratch context for A* pathfinding (reused to avoid allocation). |
管线角色 Pipeline Role
由 FFCPathingAsyncAction.h 中的异步节点(UFFCMoveTo / UFFCMoveToFlowFieldGoal)在 Activate() 中获取或新建组件并绑定 OnSuccess / OnFailed,随后调用 StartFlowFieldFollowing / StartPathFollowing / StartPathFollowingActor。每帧 TickComponent 查询 AFlowField::QueryNavigationAdvanced(FlowField 模式)或调用 AFlowField::FindPathNavMesh / FindPathAStar / GetSteeringDirection(Path 模式)。到达/失败后广播委托,异步节点回调 HandleSuccess / HandleFailed 并 SetReadyToDestroy。
The async nodes in FFCPathingAsyncAction.h (UFFCMoveTo / UFFCMoveToFlowFieldGoal) find or create the component in Activate(), bind OnSuccess / OnFailed, then call StartFlowFieldFollowing / StartPathFollowing / StartPathFollowingActor. Each frame TickComponent queries AFlowField::QueryNavigationAdvanced (FlowField mode) or calls AFlowField::FindPathNavMesh / FindPathAStar / GetSteeringDirection (Path mode). On arrival/failure the delegates broadcast; the async nodes' HandleSuccess / HandleFailed run and SetReadyToDestroy.