MassBattle Docsv1.19.20

MassBattleDebuggerCore.h

C++ Class ×1 enum class ×2 Struct ×5

Source/MassBattleEditor/Public/MassBattleDebuggerCore.h

概述 Overview

只读 MassBattle 调试核心:实体/池统计、直连 fragment 的调试绘制(并行收集 + 游戏线程刷新)、按名反射解析的实体头顶数值叠加。全部为 FMassBattleDebuggerCore 的静态函数,无实例状态(绘制队列除外)。绝不写实体/池状态;从 Slate tick 在游戏线程运行——此时 world tick 未运行,Mass 数据结构稳定,与 processor 并行 chunk 读取同级安全。

Read-only MassBattle debugging core: entity/pool stats, direct fragment-based debug drawing (parallel gather + game-thread flush), and on-entity value text overlays resolved by name. Everything is a static function of FMassBattleDebuggerCore; no instance state (apart from the draw queues). It never writes entity/pool state and runs on the game thread from Slate tick — the world tick is not running then, Mass data is structurally stable, the same read-safety class as processor parallel chunk walks.

调试器直接从 fragment 读取并绘制,绝不经过 processor;绘制设置(FMBDebugDrawSettings)刻意独立于 dataasset 驱动的 FAgentDebug / bDrawDebugShape 开关——工具自有词汇表,互不干扰。绘制走「ParallelFor 收集 → 合并 → 确定性排序 → 按类别去重 UID 截断 → DrawDebug*(Duration=0)」管线,每编辑器帧由面板重绘。

The debugger draws from fragments directly, never via processors; its draw settings (FMBDebugDrawSettings) are intentionally independent of the dataasset-driven FAgentDebug / bDrawDebugShape toggles — a tool-owned vocabulary that does not interfere with them. Drawing goes through a "parallel gather → merge → deterministic sort → per-category distinct-UID cull → DrawDebug* (Duration=0)" pipeline, redrawn every editor frame by the panel.

EMBDebugCategory enum class

调试器统计面板跟踪的实体类别。普通实体类别(Agent~Debuff)对应各自的 tag 查询;宿主(host)类别对应 EHostEntityType,其中 FxCPUHost 是 Fx 宿主中带 FCpuInterpTag 的子型。COUNT 为类别计数,不作为类别使用。显示名见 GetCategoryDisplayName。

Entity categories tracked by the debugger stats panel. Plain entity categories (Agent through Debuff) map to their respective tag queries; host categories map to EHostEntityType, where FxCPUHost is the FCpuInterpTag-carrying subtype of Fx hosts. COUNT is the category count, not a category itself. Display names come from GetCategoryDisplayName.

值 Value显示名 Display说明 Description
AgentAgent战斗单位实体。Combat agent entities.
ProjectileProjectile弹丸实体。Projectile entities.
LootLoot战利品实体。Loot entities.
FxEntityFxEntity批量特效实体。Batched FX entities.
ObstacleObstacle障碍实体(不进入池化生命周期,全部计为活跃)。Obstacle entities (never in the pooled lifecycle; all reported active).
DebuffDebuffdebuff 实体(同上,全部计为活跃)。Debuff entities (likewise all reported active).
ActorHostActor HostActor 宿主。Actor hosts.
FxHostFx Host特效宿主(GPU 插值)。FX hosts (GPU interpolation).
FxCPUHostFx Host (CPU)特效宿主中带 FCpuInterpTag 的 CPU 子型。CPU subtype of Fx hosts carrying FCpuInterpTag.
SoundHostSound Host音效宿主。Sound hosts.
ProjectileHostProjectile Host弹丸宿主。Projectile hosts.
AgentHostAgent HostAgent 宿主(持有实体而非 UObject)。Agent hosts (hold entities, not UObjects).
LootHostLoot Host战利品宿主。Loot hosts.
COUNT—类别计数(数组定长用)。Category count (for array sizing).

EMBDebugShape enum class

绘制管线刷新的形状类型——每种一一对应一次 DrawDebug* 调用。Sector 例外地拆为「弧线 + 两条边线」(引擎的 UMassBattleSubsystem::DrawDebugSector 是 private,这里自绘等价形状:水平面、偏航扫掠)。

Shape kinds flushed by the draw pipeline — each maps 1:1 to a DrawDebug* call, with Sector as the exception: it is drawn as an arc plus two edge lines (the engine-side UMassBattleSubsystem::DrawDebugSector is private, so an equivalent shape is drawn manually: horizontal plane, yaw sweep).

值 Value说明 Description
Sphere球(DrawDebugSphere,12 段)。Sphere (DrawDebugSphere, 12 segments).
Line线段(DrawDebugLine)。Line (DrawDebugLine).
Arrow方向箭头(DrawDebugDirectionalArrow)。Directional arrow (DrawDebugDirectionalArrow).
Circle圆(DrawDebugCircle,48 段)。Circle (DrawDebugCircle, 48 segments).
Capsule胶囊(DrawDebugCapsule;flush 时高度折半并做 ≥0.01 防闪烁钳制)。Capsule (DrawDebugCapsule; height halved at flush with a ≥0.01 anti-flicker clamp).
Sector扇形(DrawDebugCircleArc + 两条边线)。Sector (DrawDebugCircleArc + two edge lines).
String文本(DrawDebugString)。Text (DrawDebugString).

结构体 Structs

FMBDebugDrawItem

单一 gatherer 的变体绘制项:Shape 判别用哪个载荷,七种形状的配置(Sphere/Line/Arrow/Circle/Capsule/Sector/String)并排存放。之所以用「单一变体队列」而非多个类型化 gatherer:FParallelGatherer 的 TLS 缓存每线程只记住一个缓冲区,若在逐实体 worker 循环内交替使用多个类型化 gatherer,每次调用都会申领新槽并耗尽 MaxSlots=64(check 失败)——单一变体队列 = 每线程每帧一槽。

Single-gatherer variant draw item: Shape discriminates which payload is used; the seven shape configs (Sphere/Line/Arrow/Circle/Capsule/Sector/String) sit side by side. The reason for one variant queue instead of several typed gatherers: an FParallelGatherer's TLS cache holds ONE buffer per thread, so alternating multiple typed gatherers inside a per-entity worker loop would claim a new slot on every call and exhaust MaxSlots=64 (a check failure) — one variant queue = one slot per thread per frame.

成员变量 Members
名称 Name类型 Type默认值说明 Description
ShapeEMBDebugShapeSphere形状判别字段。Shape discriminator.
SortKeyint320排序键 = FDeterminism.UniqueID(缺失时退化为句柄 Index)——刷新时按它稳定排序,保证确定性刷新顺序。Sort key = FDeterminism.UniqueID (falls back to the handle index) — the flush stable-sorts by it for a deterministic flush order.
Catuint80EMBDebugCategory 值——刷新时按类别做 MaxCount 预算。EMBDebugCategory value — drives the per-category MaxCount budget at flush.
Sphere / Line / Arrow / Circle / Capsule / Sector / StringFDebugSphereConfig 等(引擎类型)—七种形状各自的绘制配置载荷(位置/半径/颜色/时长等);仅 Shape 指向的那份有效。注意刷新时统一取全局 LineThickness,逐项线宽刻意被忽略。Per-shape draw payload (location/radius/color/duration etc.); only the one selected by Shape is meaningful. Note the flush uses the global LineThickness; per-item thickness is ignored on purpose.
FMBDebuggerRow

实体/池统计表中的一行。INDEX_NONE 表示该行不显示此列(面板渲染为「—」)。

One stats row in the entity/pool tables. INDEX_NONE marks a column as hidden for that row (the panel renders it as "—").

成员变量 Members
名称 Name类型 Type默认值说明 Description
KeyFName—行键(如 "Agent"、"Host.Fx"、"AgentState.Attacking"、"AudioComponent"),池流转按它拼接。Row key (e.g. "Agent", "Host.Fx", "AgentState.Attacking", "AudioComponent"); pool churn is spliced by key.
DisplayNameFText—本地化显示名(来自 GetCategoryDisplayName 或拼好的状态名)。Localized display name (from GetCategoryDisplayName or a composed state name).
Totalint320tag 查询数(活跃 + 池内——池内实体保留 tag)。Tag query count (active + pooled — pooled entities keep their tags).
Activeint320实体行 = Activated 标志置位数;宿主行 = !bIsPooled 计数。Entity rows: count with the Activated flag set; host rows: count of !bIsPooled.
Pooledint320池内休眠数(Total − Active)。Dormant-in-pool count (Total − Active).
HostedObjectsint32INDEX_NONE宿主行专用:当前持有的有效 UObject 数;实体行为隐藏。Host rows only: count of valid held UObjects; hidden on entity rows.
PoolSizeint32INDEX_NONE预留的「当前池内条目数」列。CollectStats 刻意不填:池内休眠实体保留 tag,Pooled 列本身就是池大小,再填会同一数字显示两遍。Reserved "current dormant entries" column. CollectStats deliberately leaves it unset: dormant pooled entities keep tags, so the Pooled column already IS the pool size — filling this would show the same number twice.
FromPoolint32INDEX_NONE本 tick 池命中数(来自池状态查询,按 Key 拼接)。This-tick pool hits (from the pool-state query, spliced by Key).
Freshint32INDEX_NONE本 tick 新建数。This-tick fresh builds.
NoteFString空自由附加文本(子系统计数、提示等);非空时面板追加一列。Free-form extra text (subsystem counters, hints); the panel appends a column when non-empty.
FMBDebugDrawSettings

工具自有的绘制设置——刻意独立于 dataasset 驱动的 FAgentDebug / bDrawDebugShape 开关。Agent 形状复刻 FAgentDebug 的词汇表但全部从 fragment 直接派生;弹丸/战利品形状集则是模拟侧 bDrawDebugShape 从未具备的成熟集(拾取半径等对玩法关键的形状模拟从不画)。

Tool-owned draw settings — intentionally independent of the dataasset-driven FAgentDebug / bDrawDebugShape toggles. The agent shapes mirror the FAgentDebug vocabulary but are all derived directly from fragments; the projectile/loot shape sets are mature sets the sim's bDrawDebugShape never had (gameplay-critical shapes like the pickup radius are never drawn by the sim).

成员变量 Members
名称 Name类型 Type默认值说明 Description
bEnableboolfalse绘制总开关。Master draw switch.
bAgentColliderbooltrue碰撞胶囊/球,红色(休眠银灰、池内深灰)。Collider capsule/sphere, red (silver when sleeping, dark gray when pooled).
bAgentPBDInflatedboolfalsePBD 膨胀胶囊(FPhysicsShared.ColliderMult 放大),青色;球冠同样用膨胀半径。PBD-inflated capsule (scaled by FPhysicsShared.ColliderMult), cyan; caps use the inflated radius too.
bAgentOrientationbooltrue前/右/上朝向三箭头(红/绿/蓝)。Forward/right/up orientation arrows (red/green/blue).
bAgentGatherboolfalse收集半径双圆(绿色,含 GatherHeight 上移的第二圈)+ 到当前目标的连线(青色)。Gather radius circles (green, second circle lifted by GatherHeight) + links to current targets (cyan).
bAgentTraceboolfalse索敌扇形 + 目标连线/标记(目标丢失时画最后已知位置的暗色球)。Trace sector + target link/marker (a dim sphere at the last known location when the target is lost).
bAgentMoveboolfalse期望速度(黄)/当前速度(白)箭头。Desired (yellow) / current (white) velocity arrows.
bAgentAvoidanceboolfalse避障半径圆(紫色)。Avoidance radius circle (purple).
bAgentLODColorboolfalse头顶 LOD 标记球(读 FVisualizing.CurrentLOD,五级配色)。LOD marker sphere above the head (reads FVisualizing.CurrentLOD, 5-level palette).
bAgentUniqueIDboolfalseUniqueID 文本标签("A#UID")。UniqueID text label ("A#UID").
bProjRadiusbooltrue弹丸碰撞半径球。Projectile collision radius sphere.
bProjVelocityArrowbooltrue航向箭头——按移动类型(弹道/追踪/插值)取各自的速度方向与大小。Heading arrow — direction and magnitude taken from the per-move-type fragment (ballistic/tracking/interped).
bProjTrajectoryboolfalse起点→终点弹道线(青色)。From→To trajectory line (cyan).
bProjTargetboolfalse目标实体标记(橙色球);无有效目标时画终点标记。Target entity marker (orange sphere); falls back to an endpoint marker with no valid target.
bProjStateTextboolfalseUID + 状态文本(池内时附 "pool(剩余秒)")。UID + state text (pooled entities append "pool(countdown seconds)").
bLootPickupRadiusbooltrue拾取半径球,绿色(拾取半径对玩法关键,模拟侧从不画)。Pickup radius sphere, green (gameplay-critical; never drawn by the sim).
bLootCollisionRadiusboolfalse碰撞半径球,橙色。Collision radius sphere, orange.
bLootStateTextboolfalse状态色文本(状态配色镜像 loot processor:Spawning 黄 / Ready 绿 / BeingCollected 青 / Collected 蓝 / Expired 红)。State-colored text (state palette mirrors the loot processor: Spawning yellow / Ready green / BeingCollected cyan / Collected blue / Expired red).
bLootCollectorLinkboolfalse到收集者实体的连线(青色)。Line to the collector entity (cyan).
bLootTrajectoryboolfalse生成/收集弹道线(From→To)。Spawn/gather trajectory line (From→To).
MaxCountPerCategoryint32200每类别实体数上限;0 = 不限。刷新时排序后按去重 UID 截断——超出预算的实体丢弃其全部形状。Per-category entity budget; 0 = unlimited. Rank cull after sort on distinct UIDs at flush — entities beyond the budget drop ALL their shapes.
MaxDrawDistancefloat0距离剔除半径(cm);0 = 不限。对照 UMassBattleSubsystem 缓存的调试相机位置(与 processor 入队时语义一致)。Distance-cull radius (cm); 0 = unlimited. Compared against the debug camera location cached by UMassBattleSubsystem (same semantics as processor enqueue time).
LineThicknessfloat1.f所有绘制形状的统一线宽——一个旋钮等比控制全部形状(逐项线宽刻意被忽略)。Global thickness for every drawn shape — one knob scales everything uniformly (per-item values ignored on purpose).
bDrawPooledDimmedbooltrue池内(Activated 已清)实体以暗色绘制;关闭则完全跳过。Draw pooled (Activated-cleared) entities dimmed; off skips them entirely.
FMBOverlayEntry

一条实体头顶数值叠加:按名反射解析 FragmentName.PropertyName(在已注册 fragment 集上),把实时值用 DrawDebugString 画在每个匹配实体的世界位置上。

One on-entity value overlay: resolves FragmentName.PropertyName by reflection over the registered fragment set and renders the live value as DrawDebugString text at each matching entity's world location.

成员变量 Members
名称 Name类型 Type默认值说明 Description
FragmentNameFName—fragment 反射名,无 F 前缀("Health"、"LootParams" 等);解析大小写不敏感且前缀可选。Script-struct name without the F prefix ("Health", "LootParams", ...); resolution is case-insensitive with an optional prefix.
PropertyNameFName—该 fragment 上的属性名(经 TFieldRange<FProperty> 枚举)。Property on that fragment (enumerated via TFieldRange<FProperty>).
CategoryEMBDebugCategoryAgent限定叠加作用的实体类别(决定用哪个 tag 查询取实体)。Entity category the overlay applies to (decides which tag query fetches the entities).
FMBOverlaySettings

叠加过滤:距离对照缓存的调试相机、UID 白名单、按类别数量上限。

Overlay filters: distance vs the cached debug camera, a UID whitelist, and a per-category max count.

成员变量 Members
名称 Name类型 Type默认值说明 Description
bEnableboolfalse叠加总开关。Master overlay switch.
MaxCountint32100每类别实体数上限;0 = 不限。排序后按去重 UID 截断。Per-category entity budget; 0 = unlimited. Rank cull after sort on distinct UIDs.
MaxDistfloat0距离上限(cm);0 = 不限(相机缓存有效时才启用)。Distance limit (cm); 0 = unlimited (applied only when the camera cache is valid).
LineStepScalefloat1.f行距倍率:基准行距 = 相机距离 × 0.015(钳制 [2.5, 150]cm;相机无效时固定 7.5cm),乘以本值。Row spacing multiplier on the base step (camera distance × 0.015, clamped to [2.5, 150] cm; fixed 7.5 cm with no valid camera).
UidFilterTSet<int32>空UID 白名单;空 = 全部实体。UID whitelist; empty = all entities.

公开方法 Public Methods

GetGameWorlds static void

枚举全部活跃游戏世界:遍历 GEngine->GetWorldContexts(),收集 WorldType 为 PIE 或 Game 的有效世界(AddUnique 去重)。编辑器世界、预览世界不在其列;未运行 PIE/游戏时输出为空——面板据此显示 "no game world — start PIE"。

Enumerates all live game worlds: walks GEngine->GetWorldContexts() and collects valid worlds whose WorldType is PIE or Game (deduplicated via AddUnique). Editor and preview worlds are excluded; the output is empty when PIE/game is not running — the panel then shows "no game world — start PIE".

Input
参数 Param类型 Type说明 Description
OutWorldsTArray<TWeakObjectPtr<UWorld>>&输出数组,进入前先 Reset。Output array; reset before filling.
Output

无返回值。副作用:仅写输出数组;GEngine 为空时直接清空返回。

No return value. Side effect: writes the output array only; returns empty immediately when GEngine is null.

CollectStats static void

把全部统计行快照进一张表,按 UI 频率调用(内部遍历 EntityManager,不要逐帧调用)。流程:① 普通实体类别——各类别一次 tag 查询得 Total;Agent 额外在同一次并行遍历里直接读 FEntityFlagFragment 做完整状态标志直方图(11 个固定状态行:Appearing/Sleeping/Patrolling/Attacking/Chasing/Approaching/BeingHit/Falling/BeingPushed/Launching/Dying),比子系统计数器更全的 ground truth;Obstacle/Debuff 从不进入 Activated/回收生命周期,全部计为活跃并跳过标志普查。② 宿主遍历——单次 FHostControllerTag 扫描,按 config fragment 分型到 7 行(Actor/Fx/FxCPU/Sound/Projectile/Agent/Loot;Fx 与 FxCPU 经 FCpuInterpTag 区分),统计持有 UObject 数并按 bIsPooled 拆分。③ 池流转拼接——经 UMassBattleFuncLib::GetPoolStates 把每 tick 的 FromPool/Fresh 拼进对应行;池大小刻意不拼(Pooled 列即池大小);音频组件是 UObject 池,单独成行,活跃持有数来自 Sound 宿主遍历。

Snapshots all stats rows into one table; called at UI cadence only (it walks the EntityManager — do not call per frame). Flow: ① plain entity categories — one tag query per category for Total; for Agents, the same parallel pass reads FEntityFlagFragment directly to build a full state-flag histogram (11 fixed state rows: Appearing/Sleeping/Patrolling/Attacking/Chasing/Approaching/BeingHit/Falling/BeingPushed/Launching/Dying) — ground truth richer than the subsystem's processor-updated counters; Obstacles/Debuffs never enter the Activated/recycle lifecycle, so all are reported active and the flag census is skipped. ② host walk — a single FHostControllerTag pass dispatches by config fragment into 7 rows (Actor/Fx/FxCPU/Sound/Projectile/Agent/Loot; Fx vs FxCPU via FCpuInterpTag), tallying held UObjects and splitting by bIsPooled. ③ pool churn splice — per-tick FromPool/Fresh from UMassBattleFuncLib::GetPoolStates spliced into the matching rows; pool sizes are intentionally NOT spliced (the Pooled column already equals the pool size); audio components are a UObject pool and get their own row, with the active-held count from the sound host walk.

Input
参数 Param类型 Type说明 Description
WorldUWorld*目标游戏世界;无效或 MassAPI 子系统取不到时直接返回。Target game world; returns immediately when invalid or the MassAPI subsystem is unavailable.
OutRowsTArray<FMBDebuggerRow>&输出行数组,进入前先 Reset。Output row array; reset before filling.
Output

无返回值。副作用:仅写输出数组——对实体/池状态零写入。

No return value. Side effect: writes the output array only — zero writes to entity/pool state.

DrawWorld static void

按设置直接从 fragment 绘制全部启用的 pass(Duration=0,每编辑器帧由面板重绘)。流程:① 对 Agent / Projectile / Loot 三类各取 tag 句柄,仅当对应形状组有开关打开才启动该 pass;② ParallelFor 逐实体收集——无 FLocating 跳过、超距剔除(对照子系统缓存的调试相机)、未激活实体按 bDrawPooledDimmed 决定暗色绘制或跳过;条目 SortKey = FDeterminism.UniqueID(退化句柄 Index)写入全局唯一绘制队列 GDrawQueue;③ 游戏线程刷新——Merge → 按 SortKey 稳定排序 → 按类别去重 UID 的 MaxCount 截断(镜像 ProcessDrawDebugQueues 的 rank 语义)→ 直接 DrawDebug*,全部形状统一用全局 LineThickness。

Draws every enabled pass directly from fragments per the settings (Duration=0, redrawn every editor frame by the panel). Flow: ① fetch tag handles for Agent / Projectile / Loot, launching a pass only when at least one of its shape toggles is on; ② parallel per-entity gather — skip without FLocating, distance-cull against the subsystem's cached debug camera, and honor bDrawPooledDimmed for inactive entities; items keyed by SortKey = FDeterminism.UniqueID (falling back to the handle index) go into the single global draw queue GDrawQueue; ③ game-thread flush — merge → stable sort by SortKey → per-category distinct-UID MaxCount cull (mirroring the rank semantics of ProcessDrawDebugQueues) → direct DrawDebug* calls, all shapes using the global LineThickness.

Input
参数 Param类型 Type说明 Description
WorldUWorld*目标世界;无效或 bEnable 关闭时直接返回。Target world; returns immediately when invalid or bEnable is off.
Settingsconst FMBDebugDrawSettings&绘制设置(见结构体一节)。Draw settings (see the struct section).
Output

无返回值。副作用:向引擎调试绘制系统发出一批 Duration=0 的形状(单帧可见,靠每帧重绘维持);重置并重填静态绘制队列 GDrawQueue。

No return value. Side effects: emits a batch of Duration=0 shapes into the engine debug-draw system (one-frame lifetime, sustained by per-frame redraw); resets and refills the static draw queue GDrawQueue.

GetWatchableFragmentNames / GetWatchablePropertyNames static void

「按名 watch」注册表查询(Niagara 调试器式):GetWatchableFragmentNames 列出全部已注册可 watch 的 fragment 反射名(惰性一次性注册表,精选自携带有效调试状态的插件 fragment——FMainType 到 FPhysicsShared/FLODShared 共约 60 项,含普通/共享 fragment、弹丸/战利品/宿主/障碍/debuff 各型);GetWatchablePropertyNames 先按名解析 fragment(大小写不敏感、F 前缀可选),再经 TFieldRange<FProperty> 列出其全部属性名。解析失败输出为空。

Name-registry queries for Niagara-style watching: GetWatchableFragmentNames lists every registered watchable fragment name (a lazy one-time registry curated from plugin fragments carrying meaningful debug state — roughly 60 entries from FMainType through FPhysicsShared/FLODShared, covering plain/shared fragments, projectile/loot/host/obstacle/debuff variants); GetWatchablePropertyNames resolves the fragment by name (case-insensitive, optional F prefix), then lists all its property names via TFieldRange<FProperty>. Unresolvable names yield an empty output.

Input
参数 Param类型 Type说明 Description
OutNamesTArray<FName>&输出名列表(GetWatchableFragmentNames)。Output name list (GetWatchableFragmentNames).
FragmentNameFName待解析的 fragment 名(GetWatchablePropertyNames;可带可不带 F 前缀)。Fragment name to resolve (GetWatchablePropertyNames; F prefix optional).
Output

无返回值。副作用:首次调用惰性构建静态注册表。

No return value. Side effect: the first call lazily builds the static registry.

GetCategoryFragmentNames static void

按实体类别输出精选 fragment 组合(镜像各类别的生成模板),驱动叠加行的类别过滤 fragment 选择器。仅已注册名进入 UI;组合漂移优雅降级——列了但该实体没有的 fragment 只是不绘制。Agent 24 项、Projectile/Loot 各 13 项、宿主各类 4 项(Locating/Determinism/HostHierarchy/对应 Config_Final)等。

Curated fragment composition per entity category (mirroring the build templates), driving the overlay row's category-filtered fragment picker. Only registered names reach the UI; composition drift degrades gracefully — a listed-but-missing fragment simply draws nothing on those entities. Agent lists 24 entries, Projectile/Loot 13 each, host categories 4 each (Locating/Determinism/HostHierarchy/the matching Config_Final), etc.

Input
参数 Param类型 Type说明 Description
CatEMBDebugCategory目标类别。Target category.
OutNamesTArray<FName>&输出名列表。Output name list.
Output

无返回值。副作用:仅写输出数组。

No return value. Side effect: writes the output array only.

DrawTextOverlays static void

把每条叠加的实时值画到对应实体头顶(Duration=0,每编辑器帧重绘)。逐叠加:按 Category 取实体句柄(宿主类别统一走 FHostControllerTag);ParallelFor 逐实体——锚点取自身 FLocating,缺失时回退到 FHostHierarchy.AttachmentEntity 的位置(debuff 类子实体无变换碎片,挂在目标上);距离/UID 白名单过滤;值部分经反射读取(bool → "true"/"false",枚举 → 值名,其余 ExportTextItem 文本导出,空结果记 "?"),fragment/属性未解析时行降级为仅 UID 模式(新加未选择的行也能先看到实体 UID)。多行堆叠:第 i 行位于头部锚点沿堆叠方向向下偏移 i 个行距(相机有效 → 相机朝上的屏幕式堆叠 + 距离缩放行距;无效 → 世界向上 + 固定小行距,避免服务器/PIE 初期的垃圾相机位置把行距炸到地图尺度)。刷新与形状 pass 同语义:稳定排序 + 按类别去重 UID 的 MaxCount 截断。文本形如 #UID 值(黄色)。

Draws every overlay's live value as text on its entities (Duration=0, per-editor-frame). Per overlay: fetch entity handles by Category (all host categories share the FHostControllerTag query); per entity in parallel — the anchor is the entity's own FLocating, falling back to the FHostHierarchy.AttachmentEntity location (debuff-style child entities carry no transform fragment and live on their target); distance/UID-whitelist filters; the value part is read via reflection (bool → "true"/"false", enum → value name, everything else text-exported via ExportTextItem, "?" when empty) — an unresolved fragment/property degrades the row to UID-only mode, so a freshly added row with nothing picked already shows entity UIDs. Multi-row stacking: row i sits i line steps BELOW the head anchor along the stack direction (valid camera → screen-up stacking with distance-scaled steps; invalid → world-up stacking with a fixed modest step, so the garbage camera location on server worlds / early PIE cannot blow the spacing to map scale). The flush uses the same semantics as the shape pass: stable sort + per-category distinct-UID MaxCount cull. Text looks like #UID value (yellow).

Input
参数 Param类型 Type说明 Description
WorldUWorld*目标世界;无效、bEnable 关闭或叠加为空时直接返回。Target world; returns immediately when invalid, bEnable is off, or the overlay list is empty.
Settingsconst FMBOverlaySettings&叠加过滤设置。Overlay filter settings.
Overlaysconst TArray<FMBOverlayEntry>&叠加行列表。List of overlay rows.
Output

无返回值。副作用:发出一批 Duration=0 的 DrawDebugString;使用独立的函数级静态叠加队列(与形状队列分属两个 ParallelFor 波次)。

No return value. Side effects: emits Duration=0 DrawDebugString calls; uses a separate function-local static overlay queue (a different ParallelFor wave from the shape pass).

GetCategoryDisplayName static FText

类别的本地化显示名(面板与叠加 UI 共用),如 "Agent"、"Fx Host (CPU)"。未知类别返回空文本。

Localized display name for a category (shared by the panel and overlay UI), e.g. "Agent", "Fx Host (CPU)". Returns empty text for unknown categories.

Input
参数 Param类型 Type说明 Description
CatEMBDebugCategory目标类别。Target category.
Output

返回 NSLOCTEXT 显示名;未知类别为 FText::GetEmpty()。

Returns the NSLOCTEXT name, or FText::GetEmpty() for unknown categories.

管线角色 Pipeline Role

本核心是编辑器侧调试工具链的数据层,在发布树中的唯一使用者是 SMassBattleDebuggerPanel(Slate 面板):面板 Tick(游戏线程,world tick 未运行)按节流间隔调用 CollectStats,每编辑器帧调用 DrawWorld / DrawTextOverlays;世界列表经 GetGameWorlds 刷新;叠加行的类别/fragment/属性三个下拉由 GetCategoryFragmentNames、GetWatchablePropertyNames 与 GetCategoryDisplayName 供给。数据访问全部只读:tag 查询经 UMassAPIFuncLib::GetMatchingEntities,fragment 读取经 UMassAPISubsystem 的 GetFragmentPtr / GetSharedFragmentPtr / HasFlag;距离剔除参照 UMassBattleSubsystem 缓存的调试相机位置;池流转经 UMassBattleFuncLib::GetPoolStates(宿主子系统 UMassBattleHostSubsystem 有效时)。绘制不经过任何 processor——与模拟自身的 bDrawDebugShape 路径完全独立。

This core is the data layer of the editor-side debugging toolchain; its sole consumer in the release tree is SMassBattleDebuggerPanel (the Slate panel): the panel's Tick (game thread, world tick not running) calls CollectStats at a throttled interval and DrawWorld / DrawTextOverlays every editor frame; the world list refreshes via GetGameWorlds; the overlay row's category/fragment/property pickers are fed by GetCategoryFragmentNames, GetWatchablePropertyNames and GetCategoryDisplayName. All data access is read-only: tag queries via UMassAPIFuncLib::GetMatchingEntities, fragment reads via UMassAPISubsystem's GetFragmentPtr / GetSharedFragmentPtr / HasFlag; distance culling references the debug camera location cached by UMassBattleSubsystem; pool churn via UMassBattleFuncLib::GetPoolStates (when the host subsystem UMassBattleHostSubsystem is valid). Drawing never goes through processors — fully independent of the sim's own bDrawDebugShape path.

补充说明 Notes

① 形状队列 GDrawQueue 是文件级静态单例,叠加队列则是 DrawTextOverlays 内的函数级静态——两个队列与线程的 TLS 配对开销为每帧两对,远低于 FParallelGatherer::MaxSlots = 64。② 全部绘制 Duration=0:单帧可见,靠面板每编辑器帧重绘维持,PIE 暂停时依然可见。③ Agent 状态直方图直接读 FEntityFlagFragment 的置位(无需逐标志查询),是比 processor 维护计数器更全的 ground truth。④ FMassBattleDebuggerCore 无构造逻辑、无成员变量,全部入口为 static。

① The shape queue GDrawQueue is a file-level static singleton, while the overlay queue is a function-local static inside DrawTextOverlays — two queue/thread TLS pairs per frame, well under FParallelGatherer::MaxSlots = 64. ② All drawing uses Duration=0: visible for one frame and sustained by the panel's per-editor-frame redraw, remaining visible even when PIE is paused. ③ The agent state histogram reads the set bits of FEntityFlagFragment directly (no per-flag queries) — ground truth richer than the processor-maintained counters. ④ FMassBattleDebuggerCore has no constructor logic and no member variables; every entry point is static.