UMassBattleLootMonoProcessor
Source/MassBattle/Public/Processors/MassBattleLootMonoProcessor.h
概述 Overview
战利品实体的合并模拟处理器:单查询覆盖全部 loot 变种(Ballistic 弹道 / Interped_Spawn 插值出生 / Interped_Gather 收集飞行,互斥变种以 Optional + chunk 分派)。每 tick 驱动 loot 状态机 ELootState(Spawning → Ready → BeingCollected → Collected / Expired):执行 OnBirth / OnCollectBegin / OnCollectEnd / OnDestroy 的生成内容(Actor/Fx/Sound 批量 spawn 经 UMassBattleHostSubsystem)、按状态推进移动、生命周期倒计时、被收集时给收集者加 TotalScore 并广播事件队列(OnLootSpawnQueue / OnLootCollectQueue / OnLootDestroyQueue / OnStatisticsChangeQueue)。终止的 loot 走 per-archetype 池回收(PoolDataAsset)或销毁队列。网格注册不在此处——由 GridUpdateProcessor::RebuildLootGrid 独家执行。
Merged simulation processor for loot entities: one query covers all loot variants (Ballistic / Interped_Spawn / Interped_Gather — mutually exclusive variants via Optional + chunk dispatch). Each tick drives the ELootState state machine (Spawning → Ready → BeingCollected → Collected / Expired): fires OnBirth / OnCollectBegin / OnCollectEnd / OnDestroy spawn content (Actor/Fx/Sound batches via UMassBattleHostSubsystem), advances movement per state, counts down lifespan, grants TotalScore to the collector, and broadcasts event queues (OnLootSpawnQueue / OnLootCollectQueue / OnLootDestroyQueue / OnStatisticsChangeQueue). Terminated loot goes to per-archetype pool recycle (PoolDataAsset) or the destroy queue. Grid registration is NOT here — it lives exclusively in GridUpdateProcessor::RebuildLootGrid.
继承 Inheritance
公开方法 Public Methods
构造函数。设置 bAutoRegisterWithProcessingPhases = false(手动派发)、bRequiresGameThreadExecution = true、ExecutionFlags = Standalone | Server | Client。
Constructor. Sets bAutoRegisterWithProcessingPhases = false (manually dispatched), bRequiresGameThreadExecution = true, and ExecutionFlags = Standalone | Server | Client.
Input
无参数。
No parameters.
Output
无返回值。副作用:注册为手动派发、游戏线程专用的处理器。
No return value. Side effect: registers as a manually-dispatched, game-thread-only processor.
初始化实体查询:All<FLootTag> + All<FEntityFlagFragment>(MARW) + All<FSubType, FScaling, FLootEvent, FLootMove_Interped_Gather>(MARO) + All<FLootParams, FLootParamsRT, FLocating, FRotating, FDeterminism, FLootMoving_Interped_Gather, FLootGridData, FLootVisualizing>(MARW) + Optional<FLootSpawn, FLootMove_Ballistic, FLootMove_Interped_Spawn>(MARO) + Optional<FLootMoving_Ballistic, FLootMoving_Interped_Spawn>(MARW)。移动变种互斥,chunk 级视图非空判断分派。
Initializes the entity query: All<FLootTag> + All<FEntityFlagFragment>(MARW) + All<FSubType, FScaling, FLootEvent, FLootMove_Interped_Gather>(MARO) + All<FLootParams, FLootParamsRT, FLocating, FRotating, FDeterminism, FLootMoving_Interped_Gather, FLootGridData, FLootVisualizing>(MARW) + Optional<FLootSpawn, FLootMove_Ballistic, FLootMove_Interped_Spawn>(MARO) + Optional<FLootMoving_Ballistic, FLootMoving_Interped_Spawn>(MARW). The moving variants are mutually exclusive and dispatched by non-empty chunk views.
Input
| 参数 Param | 类型 Type | 说明 Description |
|---|---|---|
EntityManager | const TSharedRef<FMassEntityManager> | Mass 实体管理器,查询初始化目标。Mass entity manager; query initialization target. |
Output
无返回值。副作用:EntityQuery 注册进处理器。
No return value. Side effect: EntityQuery registered with the processor.
每 tick 执行入口。取 UMassBattleSubsystem / UMassBattleHostSubsystem / UMassAPISubsystem / UMassBattleLootSubsystem(任一缺失返回),检查 ESubFrame::Subtick3 子帧门控。DeltaTime 取 GetCalculatedStepTime(),CurrentTime 取 GetSimulationTime()。并行遍历中逐实体执行六阶段:① OnBirth(ParamsRT.bBornFired 每实体门):执行 OnBirth 生成内容、收集 OnLootSpawn 事件并闩定;② 状态移动:Spawning+Ballistic 施加重力/地面检测/反弹/沉降,沉降后经 CollectDelay 转 Ready,已被认领则转 BeingCollected 并初始化收集插值;Spawning+InterpedSpawn 按 ML.GetLootPositionAtTime_Interped_Spawn 推进,同样判定到达;BeingCollected+Gather 朝收集者飞行,到达时把分数增量入队 LootScoreGatherer 并转 Collected(加分与统计事件在遍历后的串行排空中应用);③ Ready:被认领时转 BeingCollected 并初始化收集插值;④ 生命周期:LifeSpan 倒计时,Expired 执行 OnDestroy 生成 + OnLootDestroy 事件,Collected 执行 OnCollectEnd 生成 + OnLootCollect 事件,两者都置 PendingDestroy + 清 Activated,再按有无 PoolDataAsset 分流到 LootRecycleQueue 或 EntitiesToDestroyQueue;⑤ 旋转:bRotationFollowVelocity 时朝向速度;同时为 GPU 预测写入 FLootVisualizing.CachedVelocity / AngularVelocity(最短弧旋转增量);⑥ 调试绘制(仅 Editor):按状态着色绘制碰撞球。收集的局部事件数组在 chunk 末 append 到对应子系统队列。chunk 遍历后串行排空 LootScoreGatherer(agent StatsGatherer 模式):Merge() → bDeterministic 时按 (CollectorUID, LootUID) 确定性排序 → 按收集者分组累加写入 FStatistics.TotalScore,每收集者每 tick 恰好一个携带最终值的统计事件(尊重 FAgentEvent 开关,推入 OnStatisticsChangeQueue)→ Reset() 清零——worker 线程零跨实体片段写入,事件不依赖线程调度顺序。
Per-tick entry. Resolves UMassBattleSubsystem / UMassBattleHostSubsystem / UMassAPISubsystem / UMassBattleLootSubsystem (returns early if any is missing), gated on ESubFrame::Subtick3. DeltaTime from GetCalculatedStepTime(), CurrentTime from GetSimulationTime(). Parallel per-entity six phases: ① OnBirth (per-entity ParamsRT.bBornFired gate): fire OnBirth spawn content, collect the OnLootSpawn event, latch; ② state movement: Spawning+Ballistic applies gravity / ground check / bounce / settle, then transitions to Ready after CollectDelay, or to BeingCollected when already claimed (initializing gather interpolation); Spawning+InterpedSpawn advances via ML.GetLootPositionAtTime_Interped_Spawn with the same arrival checks; BeingCollected+Gather flies toward the collector, queueing a score delta into LootScoreGatherer on arrival and transitioning to Collected (the score grant and statistics event are applied in the serial drain after the walk); ③ Ready: when claimed, transitions to BeingCollected and initializes gather interpolation; ④ lifecycle: LifeSpan countdown — Expired fires OnDestroy spawn + OnLootDestroy event; Collected fires OnCollectEnd spawn + OnLootCollect event; both set PendingDestroy + clear Activated, then route to LootRecycleQueue or EntitiesToDestroyQueue by PoolDataAsset presence; ⑤ rotation: face velocity when bRotationFollowVelocity; write FLootVisualizing.CachedVelocity / AngularVelocity for GPU prediction (shortest-arc rotation delta); ⑥ debug drawing (Editor only): state-colored collision sphere. Per-chunk local event arrays are appended to the subsystem queues at chunk end. After the chunk walk, the serial drain of LootScoreGatherer runs (agent StatsGatherer pattern): Merge() → deterministic sort by (CollectorUID, LootUID) when bDeterministic → group by collector and add the summed FStatistics.TotalScore, exactly one statistics event per collector per tick carrying the final value (respecting FAgentEvent flags, pushed into OnStatisticsChangeQueue) → Reset() the gatherer — zero cross-entity fragment writes from worker threads, and events never depend on thread scheduling.
Input
| 参数 Param | 类型 Type | 说明 Description |
|---|---|---|
EntityManager | FMassEntityManager& | 实体管理器。Entity manager. |
Context | FMassExecutionContext& | 执行上下文,提供 fragment 视图与实体遍历。Execution context providing fragment views and entity iteration. |
Output
无返回值。副作用:推进全部 loot 实体的状态机与变换;向 MBH 的 Actor/Fx/Sound spawn 批、MB 的四个事件队列、LootRecycleQueue / EntitiesToDestroyQueue / DebugSphereQueue 写入。
No return value. Side effects: advances the state machine and transforms of all loot entities; writes to MBH's Actor/Fx/Sound spawn batches, MB's four event queues, LootRecycleQueue / EntitiesToDestroyQueue / DebugSphereQueue.
成员变量 Members
私有临时上下文,成员 LootGridDataArray(TArray<FLootGridData>)及 Reset()。
Private scratch struct with member LootGridDataArray (TArray<FLootGridData>) and Reset().
loot 到达收集者时从并行 chunk 遍历入队的分数增量记录,由 Execute 内的串行排空消费(agent StatsGatherer 模式):bDeterministic 时按 (CollectorUID, LootUID) 确定性排序,逐收集者应用,每收集者每 tick 恰好一个统计事件。
Score delta record queued from the parallel chunk walk when a loot arrives at its collector; consumed by the serial drain inside Execute (agent StatsGatherer pattern): deterministically sorted by (CollectorUID, LootUID) when bDeterministic, applied per collector with exactly one statistics event per collector per tick.
成员变量 Members
| 名称 Name | 类型 Type | 默认值 | 说明 Description |
|---|---|---|---|
Collector | FEntityHandle | — | 收集者实体句柄(排空时写入其 FStatistics.TotalScore)。Collector entity handle (its FStatistics.TotalScore is written during the drain). |
CollectorUID | int32 | -1 | 收集者 UID,排序元组第一键。Collector UID; first key of the sort tuple. |
LootUID | int32 | -1 | 被收集 loot 的 UID,排序元组第二键。UID of the collected loot; second key of the sort tuple. |
ScoreDelta | int32 | 0 | 本次加分(取 FLootParams.ScoreValue)。Score gained this pick-up (from FLootParams.ScoreValue). |
供上述串行排空的无锁 TLS 收集器。并行遍历中 push,每次 Execute 内自排空(排序 → 分组应用 → 入队统计事件)并 Reset() 清零——无跨 tick 状态。
Lock-free TLS gatherer feeding the serial drain above. Pushed during the parallel walk; self-drained (sort → grouped apply → enqueue statistics events) and Reset() within every Execute — no cross-tick state.
管线角色 Pipeline Role
注册于 UMassBattleSubsystem 的 SimStages[3],在 Debuff+Reaction 阶段(SimStages[2])之后——Reaction 标记的死亡触发 loot spawn 请求,由 UMassBattleLootSubsystem 排空生成,本处理器同帧(下一阶段)可见并驱动。只在 Subtick3 子帧运行。生成的 Actor/Fx/Sound 宿主由 UMassBattleHostSubsystem 的批次 spawn 在后续 Host 阶段(SimStages[5])落地。网格注册由 GridUpdateProcessor::RebuildLootGrid 在帧起始执行(仅 Spawning/Ready 状态且无收集者时注册)。
Registered in UMassBattleSubsystem's SimStages[3], after the Debuff+Reaction stage (SimStages[2]) — deaths marked by Reaction trigger loot spawn requests drained by UMassBattleLootSubsystem; this processor sees them the same frame (next stage) and drives them. Runs only on the Subtick3 sub-frame. Spawned Actor/Fx/Sound hosts are landed by UMassBattleHostSubsystem batches in the later Host stage (SimStages[5]). Grid registration is done by GridUpdateProcessor::RebuildLootGrid at start of frame (only Spawning/Ready states with no collector are registered).