主题
UnitState 系统
概述
UnitState 是运行时可变的单位状态标签。与静态的 UnitFilter 分类不同,状态标签可以在运行时通过 Buff、技能效果或游戏逻辑动态设置和清除。
状态标签的两个用途:
- 行为控制 — 直接影响单位行为(如
SuppressMovement阻止移动,Hidden隐藏显示) - 过滤条件 — 作为
TargetFilter.Excluded的成员,将特定状态的单位排除在攻击目标之外(如排除无敌、已死亡的单位)
关于过滤用法,参见 目标过滤系统。
引用计数与免疫机制
状态的添加和移除基于 StateCounter 的引用计数机制(SERVER):
- 引用计数:每次
AddState计数 +1,每次RemoveState计数 -1。状态在计数从 0 变为正数时激活,从正数变为 0 时清除。多个 Buff 可以独立 Add/Remove 同一状态而互不干扰。 - 免疫压制:
AddImmunity会压制指定状态——即使引用计数 > 0,状态也不生效。RemoveImmunity后若引用计数仍 > 0,状态恢复。免疫本身也是引用计数的。
csharp
// Buff A 添加无敌
unit.AddState(UnitState.Invulnerable); // 计数 1 → 无敌生效
// Buff B 也添加无敌
unit.AddState(UnitState.Invulnerable); // 计数 2 → 仍然无敌
// Buff A 到期移除
unit.RemoveState(UnitState.Invulnerable); // 计数 1 → 仍然无敌
// Buff B 到期移除
unit.RemoveState(UnitState.Invulnerable); // 计数 0 → 无敌解除
// 免疫示例
unit.AddImmunity(UnitState.SuppressMovement); // 免疫定身
unit.AddState(UnitState.SuppressMovement); // 添加定身但被免疫压制,HasState 返回 false
unit.RemoveImmunity(UnitState.SuppressMovement); // 移除免疫,定身生效战斗免疫
控制单位在战斗中的免疫能力。
| 值 | 含义 | 说明 |
|---|---|---|
Invulnerable | 无敌 | 完全免疫所有伤害。常用于出生保护、过场动画等场景。默认 AI ScanFilters 排除此状态。 |
SpellImmunity | 魔免 | 免疫法术类伤害和效果。物理攻击仍然有效。 |
Ethereal | 物免(虚无) | 免疫物理伤害。法术攻击仍然有效。与 SpellImmunity 互补。 |
Unkillable | 免死 | 生命值不会降到 0 以下,无法被击杀。仍然会受到伤害。 |
Dead | 死亡 | 系统管理,不要手动操作。 由框架在单位死亡时自动设置,编辑器中隐藏。开发者应通过 unit.Kill() 击杀单位,而不是手动 AddState(UnitState.Dead)。 |
控制限制
限制单位接受命令、移动和转向的能力。
| 值 | 含义 | 说明 |
|---|---|---|
UnCommandable | 无法被命令 | 单位无法被玩家或 AI 下达命令。 |
SuppressMovement | 暂时阻止移动 | 暂时阻止行走和寻路(如眩晕、冰冻)。单位仍可接受接近命令,解除后自动恢复执行。 |
DisableMovement | 永久禁止移动 | 永久禁止移动,不再处理接近命令。适用于固定炮台等设计。 |
SuppressTurning | 暂时阻止转向 | 暂时阻止转向(如眩晕时锁定朝向)。解除后自动恢复。 |
DisableTurning | 永久禁止转向 | 永久禁止转向,锁定当前朝向。 |
Suppress vs Disable 语义对比
| 维度 | Suppress(暂时抑制) | Disable(永久禁止) |
|---|---|---|
| 持续性 | 暂时的,通常由 Buff 设置 | 永久的,通常在 GameData 中配置 |
| 命令处理 | 仍然接受接近命令并排入队列 | 不再处理接近命令 |
| 解除后行为 | 自动恢复并执行排队的命令 | 不适用 |
| 典型场景 | 眩晕、冰冻、定身等控制效果 | 固定炮台、建筑等不可移动单位 |
Movement 和 Turning 各有一对 Suppress/Disable 状态,遵循相同的语义模式。
可见性
控制单位对其他玩家的可见性。
| 值 | 含义 | 说明 |
|---|---|---|
Hidden | 隐藏 | 单位完全不可见,对所有玩家隐藏。 |
InvisibleToEnemy | 对敌方不可见 | 敌方玩家无法看到此单位(隐身)。友方仍可见。 |
Detected | 被侦测 | 压制 InvisibleToEnemy 效果,使单位对敌方重新可见(如真视宝石、侦测技能)。 |
SuppressActor | 隐藏表现 | 隐藏单位的视觉表现(模型、特效),但逻辑实体仍然存在。 |
IgnoreSelector | 无法被搜索 | 所有基于场景范围的搜索均忽略此单位(包括 AI 扫描、技能目标选取和脚本中的范围搜索)。只有通过直接引用(如变量持有)或 Player.Units 等非范围方式才能获取到。 |
InvisibleToEnemy 与 Detected 的交互
InvisibleToEnemy 使单位进入隐身状态,敌方无法看到也无法选为目标。Detected 标签会压制隐身效果——当两个标签同时存在时,单位对敌方可见。移除 Detected 后隐身恢复。
移动特性
控制单位的移动方式。
| 值 | 含义 | 说明 |
|---|---|---|
VectorMove3D | 3D 摇杆移动 | 单位可以进行 3D 方向的摇杆移动(如飞行)。仅适用于 3D 模式游戏。 |
VectorMoveBypassOrderQueue | 施法中摇杆移动 | 允许在施法期间进行摇杆移动,不打断技能释放。 |
SuppressAutoTurningWhenMoving | 禁止自动转向 | 摇杆移动和寻路时不自动面向移动方向。适用于需要边退边攻的单位。 |
碰撞与地形
控制单位的碰撞和地形交互。
| 值 | 含义 | 说明 |
|---|---|---|
SuppressDynamicCollision | 忽略动态碰撞 | 不与其他单位发生碰撞(穿透)。 |
SuppressStaticCollision | 忽略静态碰撞 | 不与地形障碍物发生碰撞(穿墙)。 |
IgnoreTerrainHeight | 忽略地形高度 | 计算中忽略地形高度差。适用于飞行单位等不受地形影响的场景。 |
其他
| 值 | 含义 | 说明 |
|---|---|---|
Summoned | 召唤物 | 标记单位为召唤物。可用于过滤或特殊逻辑(如召唤物死亡不计统计)。 |
Illusion | 幻象 | 标记单位为幻象。通常承受额外伤害或有特殊交互。 |
UnobstructedSight | 无遮挡视野 | 视野范围为圆形,不会被障碍物阻挡(空中视野)。 |
可扩展性
UnitState 使用 [EnumExtension(Extendable = true)] 标记,游戏项目可以定义新的状态标签:
csharp
[EnumExtension(Extends = typeof(UnitState))]
internal enum ECustomUnitState
{
Stunned,
Silenced,
Rooted,
}
// 生成 → CustomUnitState.Stunned, CustomUnitState.Silenced, ...扩展 UnitState(而非直接扩展基类 UnitFilterTag)的好处是与现有基础设施无缝集成:
- 数据编辑器:状态相关的下拉列表自动出现扩展的选项
- Buff 系统:通过
AddState/RemoveState直接设置和清除自定义状态 - 过滤 API:
TargetFilter.Pass()、AIScanFilters、技能TargetingFilters直接支持扩展值作为Required或Excluded条件,零额外代码
详见 EnumExtension 工具。