9.6 KiB
Quick Design Spec: Coordinator Runtime Policy
Type: Reference / Runtime Policy System: Combat Coordinator / Minion Encounter AI Related Specs:
design/quick-specs/minion-formation-showcase-combat-2026-07-03.mddesign/quick-specs/minion-combat-feel-and-weapon-roles-2026-07-03.mdDate: 2026-07-04
Change Summary
本文整理 CoordinatorSubmodule 改造期间形成的设计约定,用于指导后续杂兵 AI、Behavior Designer 节点、波次配置和命中反馈系统的开发。
核心目标不是让杂兵完全服务玩家,也不是让杂兵无约束地追求最优围攻,而是让 Cielonos 的杂兵战形成一种“有战术倾向,但仍然镜头友好、节奏清晰、打击稳定”的中高速 ARPG 体验。
Current Implementation State
当前已经完成:
FormationProfile:使用可配置Sector描述杂兵站位区域。FormationSectorPurpose:区分Action与FreeArea。FormationTacticalRoleMask:允许 Sector 声明可接受的战术职责。CoordinatorSubmoduleprofile-driven sector assignment:旧固定 6 扇区逻辑已替换为 profile-driven runtime slots。- Stable random target:敌人取得 Sector 时,会在 Sector 内抽取一个稳定随机点,避免整齐拼阵。
FormationFrame:PlayerForward/CameraForward只作为阵型初始化方向,不再逐帧拖动已分配 Sector。- Path crossing penalty:候选 Sector 如果导致敌人从玩家附近横穿,会被显著降权。
RefreshFormationFrame():已提供手动刷新阵型方向的方法,但尚未接入自动 policy。
当前仍未完成:
- 敌人 role assignment 仍主要停留在接口和数据层,Behavior Designer 尚未真正按
FormationTacticalRole分流行为。 RefreshFormationFrame()尚未由波次、房间或 Coordinator policy 自动调用。- 玩家命中敌人后的
Movement Suppression尚未实现。 FreeArea敌人还缺少低威胁行为策略,例如展示位、待机位、挑衅、缓慢重定位。AttackToken与FormationTacticalRole还没有完全合并为统一威胁预算。
Design Principles
1. Formation is Tactical Staging, Not Real-Time Rotation
FormationProfile.referenceMode 的职责是决定阵型初始化方向,而不是让阵型每帧跟随玩家或摄像机旋转。
正确语义:
referenceMode = FormationFrame 初始化方向来源
FormationFrame.rotation = 当前战斗阶段的稳定阵型方向
Player position = 当前阵型中心,可持续跟随玩家
这样可以保留 CameraForward / PlayerForward 的战术意义,同时避免玩家转身或摄像机旋转导致敌人频繁横向移动。
2. RefreshFormationFrame is a Combat Director Event
RefreshFormationFrame() 不应在普通 AI Tick 中调用。它表示“当前战斗阶段需要重新定义舞台方向”,因此应由房间、波次、阶段切换或 Coordinator policy 触发。
推荐调用时机:
| Trigger | Rule |
|---|---|
| 新一波敌人生成 | 刷新一次,使新波次以当前镜头或玩家朝向组织阵型 |
| CombatRoom / Zone 开始 | 默认由第一次 TryAcquireSector 创建 FormationFrame,通常不需要额外调用 |
所有 Action Sector 空闲且敌人未处于攻击/受击/连段中 |
可作为重整期刷新 |
| 玩家发生大位移 | 玩家离开原战场约 8-12 米后,可刷新一次 |
| 战斗阶段切换 | 例如从玩家输出窗口切换到敌人反击窗口 |
| 特殊演出或脚本事件 | 可显式刷新,但应避免打断当前受击或攻击行为 |
不推荐调用时机:
- 玩家只是转身。
- 摄像机只是旋转。
- 敌人正在
MoveToSector。 - 玩家正在近战连段命中敌人。
- 敌人正在攻击前摇、攻击中、受击、击飞、倒地或硬直。
- Boss 战中杂兵只是辅助压力时。
推荐约束:
minRefreshInterval = 3.0s - 5.0s
largePlayerDisplacement = 8m - 12m
onlyRefreshWhenNoHighPriorityState = true
3. Hit Ownership Overrides Formation
当玩家近战命中普通杂兵时,敌人应短时间进入玩家拥有的表现窗口。这个窗口内,敌人的主动移动和阵型重定位应被抑制。
建议机制名:
Movement Suppression
Player-Owned Window
允许保留:
- 受击动画。
- 击退、浮空、牵引、倒地。
ReactionSubcontroller被动位移。FuncAnimPayload或AttackArea施加的位移。- Hit stop、camera shake、damage number、Wwise hit event。
应暂停:
MoveToSector。- 主动重新申请 Sector。
- 主动刷新 Sector 目标点。
- 主动攻击请求。
- 绕背、归位、重新排队。
建议初始数值:
| Enemy Type | Movement Suppression |
|---|---|
| 普通近战杂兵 | 0.6s - 1.0s |
ShowcaseVictim |
0.9s - 1.4s |
| 远程/轻型敌人 | 0.4s - 0.7s |
| 精英敌人 | 0.2s - 0.5s |
Boss / C1_Axe |
不走此普通规则,使用 Boss poise 机制 |
4. Threat Budget Must Be Explicit
杂兵战应有战术倾向,但不能让所有敌人同时成为高威胁单位。
Demo 阶段推荐:
maxActiveMeleeThreats = 1
maxActiveRangedThreats = 0-1
maxTotalActiveThreats = 2
defaultNonThreatRole = ShowcaseVictim / Reposition / Taunt
AttackToken 目前已经承担部分威胁预算功能,但还需要与 FormationTacticalRole 结合。未来应避免“没有攻击 token 的敌人仍继续强行攻击玩家”。
5. FreeArea is Still Formation
FreeArea 不是无规则闲逛区域,而是低威胁敌人的舞台调度区域。
推荐用途:
ShowcaseVictim:靠近玩家前场,等待被连段或压制。Reposition:填补镜头友好站位。Taunt:做低威胁展示动作或短距离摆位。Staging:等待下一次 role 切换。
FreeArea 可以比 Action 更活跃,但刷新频率仍应较低。例如每 3-6 秒、玩家大位移后、或敌人脱离镜头太久时重取目标点。
Runtime Priority Stack
杂兵 AI 的优先级建议如下:
Death / Disabled
> Hit Reaction / Player-Owned Window
> Current Attack / Telegraph / Recovery
> AttackToken / Threat Budget
> Formation Sector Assignment
> FreeArea Showcase / Reposition
> Idle / Taunt
这意味着 Formation 不是最高优先级。它负责组织战场,但不能打断受击表现、攻击前摇、击飞、倒地或玩家连段窗口。
Behavior Designer Integration Notes
现有节点:
TryAcquireSectorMoveToSectorReleaseSectorTryAcquireAttackTokenHasAttackTokenReleaseAttackToken
建议新增或扩展:
| Node | Purpose |
|---|---|
TryAcquireSectorByRole |
按 FormationTacticalRole / FormationSectorPurpose 申请 Sector |
HasAssignedRole |
行为树根据 role 分流 |
IsMovementSuppressed |
被玩家命中后阻止主动移动 |
CanRequestAttackToken |
集中检查 threat budget、受击状态、展示窗口 |
RequestFormationRefresh |
仅由波次或特殊行为触发,不放入普通移动循环 |
MoveToFormationSector |
未来替代或扩展 MoveToSector,支持到达后停留、低频重取点 |
现阶段可继续兼容旧节点,但下一阶段应优先让 L1/L2 行为树显式读取 role。
Suggested Next Implementation Order
Step 1. Movement Suppression
实现玩家近战命中后的主动移动抑制。
最低要求:
- 在敌人被玩家近战命中时记录
movementSuppressedUntil。 MoveToSector在抑制期间返回Running或进入等待,不刷新 destination。- 攻击 token 请求在抑制期间失败。
- 受击、击退、浮空等被动位移仍然保留。
Step 2. Role-Aware Behavior Tree
让杂兵行为树不再只问“有没有 Sector”,而是问“我现在是什么职责”。
优先对象:
L1_Assault_PawnL2_Assault_Stinger
Step 3. RefreshFormationFrame Policy
接入自动刷新策略,但先保守实现。
最低要求:
- 房间/波次开始时允许刷新。
- 玩家大位移后允许刷新。
- 有 cooldown。
- 有敌人处于受击、攻击、硬直时不刷新。
Step 4. FreeArea Low-Threat Behaviors
为 ShowcaseVictim / Reposition / Taunt 提供简单行为。
不要求新动画和 VFX,先通过移动、停留、朝向玩家、等待、轻微重定位完成。
Step 5. Threat Budget Unification
把 AttackToken、FormationTacticalRole、enemy rank、当前战斗阶段统一为一套 Coordinator policy。
Acceptance Criteria
- 玩家转身或旋转摄像机时,已分配 Sector 的敌人不会频繁横向重定位。
- 玩家近战命中普通杂兵后,敌人不会立刻为了 Formation 逃出玩家攻击范围。
- 敌人从一个 Sector 移动到另一个 Sector 时,优先避免从玩家身体附近横穿。
RefreshFormationFrame()只在战斗阶段断点、波次变化或大位移重整时调用。Action敌人与FreeArea敌人在行为意图上可区分。- Demo 阶段同一时间的高威胁杂兵数量可控。
C1_AxeBoss 战不被普通杂兵 Coordinator 规则误削弱。
Open Questions
Movement Suppression应放在StatusSubmodule、ReactionSubcontroller、还是专门的 AI state 中?- 玩家攻击类型如何区分 melee hit、projectile hit、support equipment hit?
RefreshFormationFrame()应由CombatRoomSubmodule、RunManager、还是 Coordinator 自身 policy 触发?FreeArea敌人是否需要单独的 low-threat token,避免所有自由人同时轻微移动造成视觉噪声?- 高难度 profile 中,
Flanker是否可以绕背攻击,还是只允许绕背施压但不攻击?