配置小队、阵型与槽位

GAIS_Cover
YuewuDev

作者

YuewuDev

创建时间: 2026年10月12日更新时间: 2026年10月12日

目录

配置小队、阵型与槽位

这一篇不只说明“挂组件、填字段”,而是完成两个可验证场景:从模板生成一支固定编队,以及把关卡里已有单位重组成小队。完成后你应该能在运行时看到成员、角色、阵型槽位、导航自适应后的站位和 Movement Intent 都能收敛。

相关文档:小队功能见 小队系统,阵型功能见 阵型系统,字段见 小队、角色与单位参数 与 阵型、槽位与导航参数。

前置条件

  1. 小队宿主 Actor 类实现 IGAIS_SquadActorInterface,并具备 UGAIS_SquadComponent、UGAIS_FormationComponent 和命令/AI 所需组件。
  2. 能加入小队的单位 Actor 具备 UGAIS_UnitComponent。如果还要接收命令,该单位必须是 Pawn/Character,并在 Pawn 上添加 UGAIS_CommandSystemComponent。
  3. 项目已经定义好角色标签和槽位标签,例如 GAIS.Role.Frontline、GAIS.Role.Ranged、GAIS.Formation.Slot.Front、GAIS.Formation.Slot.Backline。
  4. 场景里存在可用 NavMesh;如果要验证导航自适应,准备一块坡地、台阶或边缘地形。

场景一:从模板生成固定编队

先创建一个 UGAIS_FormationDefinition 子类或蓝图资产,配置一个能看出空间语义的阵型。每个槽位都要有稳定 SlotId,不要把数组下标当身份使用。为关键位置设置更高 Weight,并给槽位添加 SlotTags,例如前排槽位带 GAIS.Formation.Slot.Front,后排槽位带 GAIS.Formation.Slot.Backline。

如果阵型需要跟随小队整体朝向,例如盾墙或推进队形,保持 bHasDirection 开启。如果阵型是环形、散点、包围圈,槽位自己的旋转更重要,可以关闭整体方向语义。

然后创建 UGAIS_SquadDefinition:

  1. 设置 SquadActorClass 为小队宿主类。
  2. 在 AvailableFormations 中加入刚才的阵型。
  3. 在 AvailableRoles 中配置岗位容量、资格标签、是否必须填满和角色 StateTree。
  4. 在 DefaultUnits 中配置需要自动生成的单位类型和 DesiredRole。
  5. 配置 DefaultSquadStateTree、DefaultUnitStateTree 或角色 StateTree,让小队和单位加入后有明确行为层。
  6. 调整 SlotAssignmentSettings,让角色标签和 SlotTags 能正确匹配。
  7. 调整 DefaultMovementIntentResponseSettings 和 DefaultMovementIntentTags,决定单位离槽位多远开始移动、何时停止、用什么速度响应,以及最终 Intent 携带哪些项目语义。

运行时用 UGAIS_SquadSubsystem::CreateSquad 创建小队,并允许生成默认单位。成功后,小队会初始化 Definition,FormationComponent 会选择可用阵型,SquadComponent 会等待阵型 ready,然后分配槽位并生成 Movement Intent。

场景二:把已有单位重组成小队

如果单位本来已经存在于关卡中,不要为了使用小队系统重新生成它们。可以用 CreateSquadFromActors 创建小队宿主,并把已有 Actor 加入小队。每个 Actor 必须有 UGAIS_UnitComponent、尚未属于其他小队,并满足 Unit/StateTree 运行时契约;任一 Actor 无法接纳时,整个创建事务返回 null,不会留下半支小队。

如果单位平时是独立单位,到了某个条件才被招募,确保它们已由 UGAIS_UnitComponent 自动注册到 UGAIS_SquadSubsystem,再用 CreateSquadFromNearbyUnits 从小队生成位置附近招募指定数量的未入队单位。该入口要求权威端、搜索半径大于 0 且招募数量大于 0;找不齐或候选无法完整加入时同样返回 null。战斗中需要补员时,用 TryReorganizeSquad 招募附近可自动招募单位并尝试补齐缺失角色。两支队伍需要合并时,用 MergeSquads,主小队会保留身份和高层命令语义。

重组后要验证的不只是成员数量。你还需要确认角色容器重算、必需角色缺口、槽位重分配和 Movement Intent 刷新都发生了。若单位离开小队,Unit 的 Squad 层 StateTree 应被清除,并回退到自身行为层。

多人游戏中从客户端调整小队

  1. 先确认小队成员、角色、TeamId、阵型和命令都由服务端维护。
  2. 服务端 AI、Subsystem 或权威脚本直接调用 AddUnit、AssignRoleToUnit、SetCurrentFormation 等权威入口。
  3. 拥有小队宿主的客户端使用 Server Add/Remove Unit、Server Assign/Revoke Role、Server Set Current Formation 或 Server Issue Squad Command。
  4. 客户端不拥有小队宿主时,从自己的 PlayerController 发送项目 RPC,由服务端验证玩家权限后再调用 GAIS 权威入口。
  5. 验证服务端和客户端的 UnitsContainer、RoleContainer、CurrentFormation 与 Unit 镜像最终一致。

配置导航自适应

在小队宿主的 UGAIS_FormationComponent 上检查 Navigation Adaptation:

配置

建议

bEnabled

大多数需要真实移动的项目建议开启。关闭后槽位只按几何位置展开。

NavigationQueryFilterClass

如果不同兵种或小队有不同可走区域,配置项目自己的 QueryFilter。

ProjectionQueryExtent

槽位可能位于坡地、台阶或高度变化区域时适当增大 Z。

ReprojectionDistanceThreshold / ReprojectionYawThresholdDegrees

移动频繁的大型小队可调大,减少重复投射。

bUseFallbackProjection / FallbackSearchRadius

地形边缘、桥面或障碍附近建议开启,失败时向阵型 root 方向收缩。

验证时让小队宿主移动到坡地或 NavMesh 边缘,观察槽位世界位置是否落到可导航区域。如果槽位预览 Actor 开启,预览应跟随阵型移动并反映导航偏移。

验证

  • GetInitializationState() 为 Active,且 IsSquadActive() 为 true;若仍为等待状态,继续检查 Formation 是否 ready。
  • RoleContainer 中每个角色的当前人数、MaxNum 和 bRequired 状态符合 Definition。
  • FormationComponent 有当前阵型,IsFormationReady 为 true,槽位数量和资产定义一致。
  • 用 QuerySlots 或 FindSlotRuntimeView 能看到稳定 SlotId、SlotTags 和世界变换;不要按旧状态字段或数组下标推断可用性。
  • 每个应参与编队的 Unit 都有合理 AssignedSlotId。
  • Movement Intent 中能看到 RawDesiredLocation、DesiredLocation、DesiredOrientation、DesiredSpeed、bShouldMove 和 MovementIntentTags。
  • GameplayDebugger 的 Squad / Formation 段能看到成员、角色、当前阵型、槽位和 slot-score 解释。

常见失败

现象

优先检查

小队初始化卡住

FormationComponent 是否存在,AvailableFormations 是否可加载,当前阵型是否 ready。

单位加入小队但没有角色

AvailableRoles 是否包含该角色,IsQualifiedOfRole、AllowedClasses、RequiredTags、BlockTags 是否挡住。

单位没有槽位

槽位数量是否不足,SlotTags 策略是否过严,SlotAssignmentSettings 是否让距离或稳定性压过语义匹配。

槽位位置在不可走区域

Navigation Adaptation 是否开启,QueryFilter/ProjectionQueryExtent 是否适合当前 NavMesh,fallback 半径是否太小。

Movement Intent 有值但单位不动

是否配置了 MovementIntentDriver,或项目移动系统是否消费 UnitComponent 上镜像的 Intent。

客户端点击改编队但没反应

是否误调了只限权威端的入口;如已调用 Server...,再确认该客户端是否拥有小队宿主或 Owner 链。