UMassBattleObstacleBoxComponent
Source/MassBattle/Public/Components/MassBattleObstacleBoxComponent.h
概述 Overview
盒体障碍物组件,派生自 UBoxComponent,与胶囊/样条组件构成 MassBattle 三类障碍物。职责:① 在 BeginPlay 向 UMassBattleObstSubsystem 注册(子系统按位置排序后确定性生成实体),EndPlay 注销(实体随之销毁);② 命令/本地路由由子系统在注册时按「会话 × owner 复制状态」决定并写入 bCommandRouted(替代已移除的每组件 bLockstepNetworked):true → 命令路径,组件变换经 Obstacle.SyncTransform 锁步指令每模拟 tick 同步给实体(组件→实体)、销毁经 Obstacle.Destroy 指令双端收敛;false → 本地派生 UID 路径(锁步会话中布防位移监视——运行时位移会响亮报错)。动态障碍走命令路径时校验 owner 须开启 Replication + ReplicateMovement(违规 Error 日志)。另提供 bForceHybridAgentUseForceFieldMode 覆盖 Hybrid agent 的避障求解器选择。
Box obstacle component, derived from UBoxComponent — one of the three MassBattle obstacle types (box / capsule / spline). Responsibilities: ① registers with UMassBattleObstSubsystem in BeginPlay (the subsystem sorts all obstacles by location and spawns entities deterministically), unregisters in EndPlay (entity destroyed with it); ② command-vs-local routing is decided by the subsystem at registration from "session × owner replication state" and stamped into bCommandRouted (replacing the removed per-component bLockstepNetworked): true → command path, where the component transform syncs to the entity via the Obstacle.SyncTransform lockstep command each simulation tick (component→entity) and teardown converges both peers via Obstacle.Destroy; false → local derived-UID path (in lockstep sessions a displacement watch is armed — runtime movement fails loud). Dynamic obstacles on the command path require the owner to enable Replication + ReplicateMovement (violations log Error at startup). Also provides bForceHybridAgentUseForceFieldMode to override the Hybrid-agent avoidance solver choice.
继承 Inheritance
公开方法 Public Methods
允许 tick(bCanEverTick = true),但默认不开启(bStartWithTickEnabled = false)——命令路由(bCommandRouted)或锁步会话中的本地路径(位移监视)在 BeginPlay 开启。
Allows ticking (bCanEverTick = true) but does not start with it enabled (bStartWithTickEnabled = false) — enabled in BeginPlay for command routing (bCommandRouted) or the local path inside a lockstep session (displacement watch).
Input
无参数。
No parameters.
Output
无返回值。副作用:tick 配置。
No return value. Side effect: tick configuration.
① 调用父类;② 向 UMassBattleObstSubsystem::RegisterBoxObstacle 注册本组件(子系统按「会话 × owner 复制状态」路由并写入 bCommandRouted,随后对全部障碍物按位置排序确定性生成实体);③ 命令路径(bCommandRouted):仅动态 + 复制 owner 校验 ReplicateMovement(静态障碍以注册时变换单次注册,无需运动通道;非复制地图障碍物按路径解析,无需检查;违规 Error 日志),以当前变换为同步基线(LastSyncedTransform —— Spawn 指令携带相同初始变换),开启组件 tick;④ 锁步会话中的本地路径:布防位移监视(基线 = 注册时变换),开启 tick。
① Calls the parent; ② registers with UMassBattleObstSubsystem::RegisterBoxObstacle (the subsystem routes by "session × owner replication state" into bCommandRouted, then sorts all obstacles by location and spawns entities deterministically); ③ command path (bCommandRouted): validates ReplicateMovement only for dynamic + replicated owners (static obstacles register once with the registration-time transform and need no movement channel; non-replicated map obstacles resolve by path, no check; violations log Error), sets the current transform as the sync baseline (LastSyncedTransform — the Spawn command carries the same initial transform) and enables component ticking; ④ local path inside a lockstep session: arms the displacement watch (baseline = registration transform) and enables ticking.
Input
无参数。
No parameters.
Output
无返回值。副作用:子系统注册;锁步模式下开启 tick 与基线记录。
No return value. Side effects: subsystem registration; in lockstep mode, tick enablement and baseline capture.
先拆除宿主注册表(LockstepNetID ≥ 0 时经 UMassBattleNetworkSubsystem::UnregisterLockstepHost)。命令路由(bCommandRouted)且实体已构建(LockstepEntityUIDs 非空)时:经 GameMode 广播 Obstacle.Destroy 锁步指令(UID 载荷),双端收敛销毁,跳过本地注销路径;否则调用 UMassBattleObstSubsystem::UnregisterBoxObstacle 本地注销(销毁实体)。无论哪条路径都经 RemoveCommandRoutedObstacle 从清单登记表移除。最后调用父类。
First tears down the host registry (LockstepNetID ≥ 0 → UMassBattleNetworkSubsystem::UnregisterLockstepHost). In command-routed mode (bCommandRouted) with entities built (LockstepEntityUIDs non-empty): broadcasts the Obstacle.Destroy lockstep command via the GameMode (UID payload) so both peers converge, skipping the local unregister path; otherwise calls UMassBattleObstSubsystem::UnregisterBoxObstacle for local teardown (destroys the entity). Either way the component is dropped from the manifest registry via RemoveCommandRoutedObstacle. Then calls the parent.
Input
| 参数 Param | 类型 Type | 说明 Description |
|---|---|---|
EndPlayReason | EEndPlayReason::Type | 结束播放原因。End-play reason. |
Output
无返回值。副作用:锁步销毁指令广播,或子系统注销(实体销毁)。
No return value. Side effects: lockstep destroy command broadcast, or subsystem unregistration (entity destruction).
先调用父类,随后三段:① 重绑重试(bPendingRebind 且未放弃):限频约每 30 帧一次,上限 200 次——超限视为联结键失配,响亮 Error 并放弃(直至 OnRep / 快照恢复重启策略),键失配绝不许每帧烧一次全实体表扫描;② 本地路径(bCommandRouted 为 false):位移监视——单机直接停 tick 豁免;锁步会话中对照注册基线比较,位移即一次性 Error(无同步通道,双端避障网格会分歧)并停 tick;③ 命令路径:仅服务器权威;每模拟 tick 最多一次(LastCheckedTick 与 UMassBattleSubsystem::GetTickCount 比较);Spawn 指令未执行(LockstepEntityUIDs 为空)时跳过;组件变换与基线 LastSyncedTransform 相等时跳过;变化时经 GameMode 广播 Obstacle.SyncTransform 锁步指令,载荷 FloatPayload = [位置 XYZ, 四元数 XYZW, 缩放 XYZ]。
Calls the parent first, then three sections: ① pending-rebind retry (bPendingRebind, not abandoned): throttled to roughly every 30 frames and capped at 200 attempts — exceeding the cap means a mismatched join key: a loud Error is logged and retrying stops (until OnRep / snapshot restore re-arms the policy); a mismatched key must never burn a full entity-map scan every frame. ② Local path (bCommandRouted false): displacement watch — standalone stops ticking immediately (exempt); in lockstep sessions the transform is compared against the registration baseline, and movement triggers a one-time Error (no sync channel — the peers' avoidance grids diverge) then stops ticking. ③ Command path: server-authoritative only; at most once per simulation tick (LastCheckedTick vs UMassBattleSubsystem::GetTickCount); skipped while the Spawn command has not executed (LockstepEntityUIDs empty); skipped when the component transform equals the LastSyncedTransform baseline; on change broadcasts the Obstacle.SyncTransform lockstep command via the GameMode with FloatPayload = [location XYZ, quaternion XYZW, scale XYZ].
Input
| 参数 Param | 类型 Type | 说明 Description |
|---|---|---|
DeltaTime | float | 本帧时间步长(秒)。Frame delta time in seconds. |
TickType | ELevelTick | tick 类型。Tick type. |
ThisTickFunction | FActorComponentTickFunction* | tick 函数对象。Tick function object. |
Output
无返回值。副作用:变换变化时广播 Obstacle.SyncTransform 指令并更新基线。
No return value. Side effect: broadcasts Obstacle.SyncTransform on transform change and updates the baseline.
LockstepNetID 复制回调——ID 有效(≥ 0)时把本组件注册进 UMassBattleNetworkSubsystem 的 LockstepRegistry(agent 对等模式),随后重启重绑重试策略(ReArmRebindRetry——新 NetID 到达 = 新纪元)并立即 RebindToEntity(快照恢复可能先于组件复制到达)。因引擎图元基类(UBoxComponent)无法继承 UMassBattleEntityComponentBase 三件套,该联结被内联到本组件。
RepNotify for LockstepNetID — with a valid ID (≥ 0) registers this component into the UMassBattleNetworkSubsystem LockstepRegistry (agent-parity pattern), then re-arms the rebind retry policy (ReArmRebindRetry — a fresh NetID arrival is a new era) and calls RebindToEntity immediately (snapshot restore may have raced ahead of component replication). Because the engine primitive base class (UBoxComponent) forbids inheriting the UMassBattleEntityComponentBase trio, the binding is inlined here.
Input
无参数。
No parameters.
Output
无返回值。副作用:LockstepRegistry 注册。
No return value. Side effect: LockstepRegistry registration.
注册 LockstepNetID 的复制属性。
Registers the replication property for LockstepNetID.
Input
| 参数 Param | 类型 Type | 说明 Description |
|---|---|---|
OutLifetimeProps | TArray<FLifetimeProperty>& | 生存期属性输出数组。Output lifetime-property array. |
Output
无返回值。
No return value.
把本组件重链到携带 FObstacleNetBinding.LockstepNetID == 本组件 ID 的实体(agent RebindToEntity 模式——幂等,实体缺席时静默重试)。非命令路由(bCommandRouted 为 false)直接返回;实体句柄仍有效则清 bPendingRebind 返回。联结键:复制 owner → NetID;非复制地图障碍物(NetID = -1)→ 归一化对象子路径(NormalizeObstacleJoinPath,PIE 下原始路径每端不同)。遍历 GlobalUIDToHandle 匹配,命中后写 FBoxObstacle.BoundComponent、EntityHandle,并从 FDeterminism.UniqueID 回写 LockstepEntityUIDs;未命中置 bPendingRebind(由 tick 限频重试)。快照恢复后由 UMassBattleObstSubsystem::RebindAllCommandRoutedObstacles 调用。
Re-links this component to the entity carrying FObstacleNetBinding.LockstepNetID == ours (agent RebindToEntity pattern — idempotent, silent retry while the entity is absent). Returns immediately when not command-routed (bCommandRouted false); clears bPendingRebind and returns while the entity handle is still valid. Join key: replicated owners → NetID; non-replicated map obstacles (NetID = -1) → the normalized object sub-path (NormalizeObstacleJoinPath; raw paths differ per peer under PIE). Iterates GlobalUIDToHandle for a match; on hit writes FBoxObstacle.BoundComponent and EntityHandle, and back-fills LockstepEntityUIDs from FDeterminism.UniqueID; otherwise sets bPendingRebind (throttled retry on tick). Called after snapshot restore by UMassBattleObstSubsystem::RebindAllCommandRoutedObstacles.
Input
无参数。
No parameters.
Output
无返回值。副作用:重建组件→实体绑定;未就绪时置 bPendingRebind。
No return value. Side effects: rebuilds the component→entity binding; sets bPendingRebind when not ready.
重启重绑重试策略(新纪元:OnRep 到达 / 快照恢复 pass)——清零 RebindThrottleCounter / RebindAttempts,清除 bRebindAbandoned。由 OnRep_LockstepNetID 调用。
Re-arms the rebind retry policy (new era: OnRep arrival / snapshot-restore pass) — zeroes RebindThrottleCounter / RebindAttempts and clears bRebindAbandoned. Called from OnRep_LockstepNetID.
Input
无参数。
No parameters.
Output
无返回值。副作用:重试策略三字段复位。
No return value. Side effect: resets the three retry-policy fields.
由 Obstacle.Spawn 命令执行端在实体构建后写入实体 UID 数组。
Writes the entity UID array after the entity is built; called by the Obstacle.Spawn command execution.
Input
| 参数 Param | 类型 Type | 说明 Description |
|---|---|---|
InUIDs | const TArray<int32>& | 实体 UID 数组。Entity UID array. |
Output
无返回值。副作用:覆写 LockstepEntityUIDs。
No return value. Side effect: overwrites LockstepEntityUIDs.
读取实体 UID 数组;空 = 尚未构建。
Reads the entity UID array; empty = not built yet.
Input
无参数。
No parameters.
Output
返回 LockstepEntityUIDs 引用。无副作用。
Returns a reference to LockstepEntityUIDs. No side effects.
成员变量 Members
是否动态障碍物。
Whether this is a dynamic obstacle.
是否激活。
Whether activated.
盒体是否"内外翻转"(盒体内部视为阻挡/可通行区域反转)。
Whether the box is inside-out (interior blocking semantics inverted).
隐藏字段 —— 尚未实现。
Hidden field — not implemented yet.
Hybrid 求解器覆盖:为真时,看到本障碍物的 Hybrid agent 对它保持 ForceField 求解(不再因接触障碍物切 ORCA)——墙体斥力推开而非速度空间约束。纯 ORCA agent 不受影响。注册时盖章进障碍物实体(网格数据标志位)——锁步安全。
Hybrid-agent solver override: when true, Hybrid agents that see this obstacle keep the ForceField solver for it instead of switching to ORCA on obstacle contact — the wall repulsion pushes through instead of velocity-space constraints. Pure ORCA agents are unaffected. Stamped into the obstacle entity (grid data flag) at registration — lockstep-safe.
运行时路由结果——障碍物子系统注册时按「会话 × owner 复制状态」写入(不序列化):true → 命令路径(Obstacle.Spawn/SyncTransform/Destroy 锁步指令),false → 本地派生 UID 路径。替代已移除的每组件 bLockstepNetworked。
Runtime routing result — written by the obstacle subsystem at registration from "session × owner replication state" (NOT serialized): true → command path (Obstacle.Spawn/SyncTransform/Destroy lockstep commands), false → local derived-UID path. Replaces the removed per-component bLockstepNetworked.
agent 对等锁步宿主联结——服务器注册时分配,OnRep / 晚 BeginPlay 注册进 LockstepRegistry,快照恢复后 RebindToEntity 重链重建实体(bPendingRebind 逐 tick 重试)。
Agent-parity lockstep host binding — server-allocated at registration, registered into the LockstepRegistry on OnRep / late BeginPlay; after snapshot restore RebindToEntity re-links the rebuilt entity (bPendingRebind retries on tick).
重绑挂起标记——目标实体尚未就绪时置位,组件 tick 中按限频策略重试 RebindToEntity(见下方重试策略字段)。
Pending-rebind flag — set while the target entity is absent; the component tick retries RebindToEntity under the throttled policy (see the retry-policy fields below).
重绑重试策略三字段:限频(约每 30 帧)+ 上限(200 次)+ 响亮失败——键失配绝不许每帧烧一次全实体表扫描。超限后置 bRebindAbandoned 停止重试,直至 ReArmRebindRetry(OnRep 到达 / 快照恢复 pass)重启。
The three retry-policy fields: throttled (~every 30 frames) + capped (200 attempts) with loud failure — a mismatched join key must never burn a full entity-map scan every frame. Past the cap bRebindAbandoned stops retrying until ReArmRebindRetry (OnRep arrival / snapshot-restore pass) re-arms the policy.
本组件关联的障碍物实体句柄。
The obstacle entity handle associated with this component.
Obstacle.Spawn 执行后的实体 UID;空 = 尚未构建。经 SetLockstepEntityUIDs/GetLockstepEntityUIDs 访问。
Entity UID(s) after Obstacle.Spawn executes; empty = not built yet. Accessed via SetLockstepEntityUIDs/GetLockstepEntityUIDs.
上次同步的变换基线;BeginPlay 时记录,TickComponent 据此跳过未变化帧。
Last-synced transform baseline; recorded in BeginPlay, used by TickComponent to skip unchanged frames.
上次检查的模拟 tick 计数,保证每模拟 tick 最多同步一次。
Last-checked simulation tick count, ensuring at most one sync per simulation tick.
管线角色 Pipeline Role
BeginPlay 向 UMassBattleObstSubsystem 注册(RegisterBoxObstacle,子系统按「会话 × owner 复制状态」写入 bCommandRouted)→ 子系统按位置排序后确定性生成障碍物实体(命令路径经 Obstacle.Spawn 锁步指令,双端执行时经 SetLockstepEntityUIDs 回写 UID)→ 命令路由时 TickComponent(服务器权威)在变换变化时经 GameMode 广播 Obstacle.SyncTransform 指令 → 销毁时经 Obstacle.Destroy 指令双端收敛(或本地 UnregisterBoxObstacle 注销)。盒/胶囊/样条三类组件在 UMassBattleObstSubsystem 与 UMassBattleHashGridSubsystem(网格注册命令)处汇合。
BeginPlay registers with UMassBattleObstSubsystem (RegisterBoxObstacle; the subsystem stamps bCommandRouted from "session × owner replication state") → the subsystem sorts by location and spawns obstacle entities deterministically (the command path via the Obstacle.Spawn lockstep command; UIDs written back through SetLockstepEntityUIDs at command execution) → when command-routed, TickComponent (server-authoritative) broadcasts Obstacle.SyncTransform via the GameMode when the transform changes → teardown converges both peers via Obstacle.Destroy (or local UnregisterBoxObstacle). All three obstacle types (box / capsule / spline) meet at UMassBattleObstSubsystem and UMassBattleHashGridSubsystem (grid registration commands).