Files
Cielonos/design/quick-specs/coordinator-runtime-policy-2026-07-04.md
SoulliesOfficial 39b43680a9 爆更
2026-07-18 03:16:20 -04:00

9.6 KiB
Raw Blame History

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.md
  • design/quick-specs/minion-combat-feel-and-weapon-roles-2026-07-03.md Date: 2026-07-04

Change Summary

本文整理 CoordinatorSubmodule 改造期间形成的设计约定,用于指导后续杂兵 AI、Behavior Designer 节点、波次配置和命中反馈系统的开发。

核心目标不是让杂兵完全服务玩家,也不是让杂兵无约束地追求最优围攻,而是让 Cielonos 的杂兵战形成一种“有战术倾向,但仍然镜头友好、节奏清晰、打击稳定”的中高速 ARPG 体验。

Current Implementation State

当前已经完成:

  • FormationProfile:使用可配置 Sector 描述杂兵站位区域。
  • FormationSectorPurpose:区分 ActionFreeArea
  • FormationTacticalRoleMask:允许 Sector 声明可接受的战术职责。
  • CoordinatorSubmodule profile-driven sector assignment旧固定 6 扇区逻辑已替换为 profile-driven runtime slots。
  • Stable random target敌人取得 Sector 时,会在 Sector 内抽取一个稳定随机点,避免整齐拼阵。
  • FormationFramePlayerForward / CameraForward 只作为阵型初始化方向,不再逐帧拖动已分配 Sector。
  • Path crossing penalty候选 Sector 如果导致敌人从玩家附近横穿,会被显著降权。
  • RefreshFormationFrame():已提供手动刷新阵型方向的方法,但尚未接入自动 policy。

当前仍未完成:

  • 敌人 role assignment 仍主要停留在接口和数据层Behavior Designer 尚未真正按 FormationTacticalRole 分流行为。
  • RefreshFormationFrame() 尚未由波次、房间或 Coordinator policy 自动调用。
  • 玩家命中敌人后的 Movement Suppression 尚未实现。
  • FreeArea 敌人还缺少低威胁行为策略,例如展示位、待机位、挑衅、缓慢重定位。
  • AttackTokenFormationTacticalRole 还没有完全合并为统一威胁预算。

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 被动位移。
  • FuncAnimPayloadAttackArea 施加的位移。
  • 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

现有节点:

  • TryAcquireSector
  • MoveToSector
  • ReleaseSector
  • TryAcquireAttackToken
  • HasAttackToken
  • ReleaseAttackToken

建议新增或扩展:

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_Pawn
  • L2_Assault_Stinger

Step 3. RefreshFormationFrame Policy

接入自动刷新策略,但先保守实现。

最低要求:

  • 房间/波次开始时允许刷新。
  • 玩家大位移后允许刷新。
  • 有 cooldown。
  • 有敌人处于受击、攻击、硬直时不刷新。

Step 4. FreeArea Low-Threat Behaviors

ShowcaseVictim / Reposition / Taunt 提供简单行为。

不要求新动画和 VFX先通过移动、停留、朝向玩家、等待、轻微重定位完成。

Step 5. Threat Budget Unification

AttackTokenFormationTacticalRole、enemy rank、当前战斗阶段统一为一套 Coordinator policy。

Acceptance Criteria

  • 玩家转身或旋转摄像机时,已分配 Sector 的敌人不会频繁横向重定位。
  • 玩家近战命中普通杂兵后,敌人不会立刻为了 Formation 逃出玩家攻击范围。
  • 敌人从一个 Sector 移动到另一个 Sector 时,优先避免从玩家身体附近横穿。
  • RefreshFormationFrame() 只在战斗阶段断点、波次变化或大位移重整时调用。
  • Action 敌人与 FreeArea 敌人在行为意图上可区分。
  • Demo 阶段同一时间的高威胁杂兵数量可控。
  • C1_Axe Boss 战不被普通杂兵 Coordinator 规则误削弱。

Open Questions

  • Movement Suppression 应放在 StatusSubmoduleReactionSubcontroller、还是专门的 AI state 中?
  • 玩家攻击类型如何区分 melee hit、projectile hit、support equipment hit
  • RefreshFormationFrame() 应由 CombatRoomSubmoduleRunManager、还是 Coordinator 自身 policy 触发?
  • FreeArea 敌人是否需要单独的 low-threat token避免所有自由人同时轻微移动造成视觉噪声
  • 高难度 profile 中,Flanker 是否可以绕背攻击,还是只允许绕背施压但不攻击?