Files
zeling_v2/Docs/Architecture/25_CharacterArchitectureOverview.md
2026-05-19 11:50:21 +08:00

639 lines
30 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 25 · 角色系统架构全景图
> **命名空间** `BaseGames.Player`、`BaseGames.Player.States`、`BaseGames.Enemies`、`BaseGames.Enemies.AI`、`BaseGames.Boss`、`BaseGames.Combat`
> **路径** `Assets/_Game/Scripts/Player/`、`Assets/_Game/Scripts/Enemies/`、`Assets/_Game/Scripts/Combat/`
> **关联文档** [05_PlayerModule](05_PlayerModule.md) · [06_CombatModule](06_CombatModule.md) · [07_EnemyModule](07_EnemyModule.md) · [09_ProgressionModule](09_ProgressionModule.md) · [23_BossSkillModule](23_BossSkillModule.md)
> **建立日期** 2026-05-17
本文档是跨模块的**角色系统实现全景图**,侧重三类角色(玩家 / 小怪 / Boss在 Scene 中的节点结构、脚本职责划分、子系统数据流与相互协作关系。各模块深度细节请参阅上方关联文档。
---
## 目录
1. [程序集依赖总览](#1-程序集依赖总览)
2. [玩家Player](#2-玩家-player)
- 2.1 [Scene 节点结构](#21-scene-节点结构)
- 2.2 [FSM 状态机](#22-fsm-状态机)
- 2.3 [数值体系 PlayerStats](#23-数值体系-playerstats)
- 2.4 [形态系统 Form System](#24-形态系统-form-system)
- 2.5 [武器系统 Weapon System](#25-武器系统-weapon-system)
- 2.6 [技能系统 Skill System](#26-技能系统-skill-system)
- 2.7 [能力解锁 AbilityType Flags](#27-能力解锁-abilitytype-flags)
- 2.8 [装备护符系统 Equipment / Charm](#28-装备护符系统-equipment--charm)
3. [小怪Enemy](#3-小怪-enemy)
- 3.1 [Scene 节点结构](#31-scene-节点结构)
- 3.2 [状态机POCO 状态)](#32-状态机poco-状态)
- 3.3 [AI — Behavior Designer 节点库](#33-ai--behavior-designer-节点库)
4. [Boss](#4-boss)
- 4.1 [继承关系](#41-继承关系)
- 4.2 [Scene 节点结构](#42-scene-节点结构)
- 4.3 [技能执行流 BossSkillSO + BossSkillExecutor](#43-技能执行流-bossskillso--bossskillexecutor)
- 4.4 [阶段切换](#44-阶段切换)
5. [共享战斗层 Combat Module](#5-共享战斗层-combat-module)
- 5.1 [核心接口](#51-核心接口)
- 5.2 [HitBox → HurtBox 伤害流水线](#52-hitbox--hurtbox-伤害流水线)
- 5.3 [状态效果系统](#53-状态效果系统)
6. [数据驱动 ScriptableObject 体系](#6-数据驱动-scriptableobject-体系)
7. [架构核心原则总结](#7-架构核心原则总结)
---
## 1. 程序集依赖总览
```
BaseGames.Core
BaseGames.Core.Events
BaseGames.Core.Save
BaseGames.Combat ──────────────────────────────────────────────┐
BaseGames.Combat.StatusEffects │
│ │
↓ ↓
BaseGames.Player BaseGames.Enemies │
BaseGames.Player.States BaseGames.Enemies.AI │
BaseGames.Skills BaseGames.Enemies.Navigation │
BaseGames.Equipment BaseGames.Enemies.Boss.Patterns │
BaseGames.Parry │
└────────────────────────────────────────────────────────┘
```
**原则**:下层程序集不得引用上层。`BaseGames.Combat` 仅依赖 `Core``Player` / `Enemies` 均依赖 `Combat` 而不互相依赖。跨层通信一律通过 `EventChannelSO``ServiceLocator` 完成。
---
## 2. 玩家Player
### 2.1 Scene 节点结构
```
[Player] ← 根节点(空 GameObject逻辑锚点
├── PLY_Player ← 核心行为节点(所有主要组件挂于此)
│ │
│ │── PlayerController ← FSM 协调器DefaultExecOrder=-100
│ │ IDamageable + IPoiseSource
│ │── PlayerMovement ← 物理移动封装DefaultExecOrder=-200
│ │ Rigidbody2D 操作 / 土狼时间 / 地面检测
│ │── PlayerStats ← 数值管理HP/灵魂/灵气/灵泉/LingZhu/能力Flags
│ │ ISaveable + IRestoreOnSave + IRewardTarget
│ │── PlayerCombat ← 连击段 DamageSource 切换 / HitBox 激活接口
│ │── FormController ← 三形态状态机(天魂/地魂/命魂)
│ │── WeaponManager ← 依形态切换 ActiveWeapon + 实例化 HitBoxPrefab
│ │── SkillManager ← 技能槽管理 / 冷却计时 / 资源消耗
│ │── SpringSystem ← 灵泉治疗充能系统
│ │── ParrySystem ← 弹反时序窗口(见 CombatModule §10
│ │── ShieldComponent ← 护盾吸收IShieldable
│ │── PlayerWallDetector ← 蹬墙感应(贴墙方向 / 触发 WallSlide 条件)
│ │── StatusEffectManager ← IStatusEffectable火 / 毒 / 硬直效果接收)
│ │── EquipmentManager ← 护符槽管理Notch 容量体系)
│ │── SkillModifierRegistry ← 护符注入的技能修改器(冷却/费用调节)
│ │── AnimancerComponent ← 动画驱动
│ │ Layer 0全身状态动画移动/攻击/受伤/死亡)
│ │ Layer 1Overlay叠加层动画灵泉/法术)
│ │── InputBuffer ← 输入缓冲RequireComponent by PlayerController
│ │── Rigidbody2D ← DynamicFreezeRotation插值关闭
│ └── CapsuleCollider2D ← isTrigger=false碰撞体
├── HurtBox ← 受击盒isTrigger=trueLayer=PlayerHurtBox
│ └── HurtBox.cs GetComponentInParent<IDamageable>() 注入
├── [WeaponSocket] ← HitBox 挂载点WeaponManager 实例化目标)
│ └── WeaponHitBoxInstance ← 由 WeaponSO.hitBoxPrefab 动态实例化/销毁
│ └── HitBox ← Layer=PlayerHitBoxisTrigger=true
├── GroundCheck ← 地面检测 TransformBoxOverlapNonAlloc 起点)
└── SkillHitBox_Slot ← 技能命中盒挂载点SkillHitBoxInstance 实例化)
```
> **命名规范**:根节点用 `[Player]`(方括号标识逻辑组节点),具体 GameObject 用 `PLY_` 前缀PascalCase子功能节点用 `[WeaponSocket]` 括号命名,检测点用描述性名称 `GroundCheck`。
---
### 2.2 FSM 状态机
`PlayerController` 持有 `Dictionary<Type, PlayerStateBase>` 状态字典,每帧驱动 `_currentState``OnStateUpdate / OnStateFixedUpdate`,并在 `TransitionTo<T>()` 时依次调用 `OnStateExit / OnStateEnter`
```
PlayerStateBase抽象 POCO不继承 MonoBehaviour
│ OnStateEnter / OnStateUpdate / OnStateFixedUpdate / OnStateExit
│ virtual bool IsInvincible → DashState override true
│ #if UNITY_EDITOR ValidTransitions → 转换白名单(调试用)
├── IdleState 落地重置 AirJumps出口Run / Jump / Dash / Attack / Spring
├── RunState 水平位移 + 朝向;出口同 Idle + WallSlide
├── JumpState 可变跳跃(松键截断 Y 速度)+ 土狼时间消耗
├── FallState FallMultiplier 下落加速贴墙→WallSlide
├── DashState IsInvincible=true地面冲刺 dashDistance / 冷却 dashCooldown
├── AerialDashState 空中冲刺消耗 _aerialDashCount落地重置次数
├── WallSlideState wallSlideSpeed 减速下滑Space → WallJump
├── WallJumpState 弹离墙壁 X+Y 分量wallJumpLockTime 方向锁定
├── AttackState 3 段连击Combo Window 计时);每段调 SetComboSegmentSource
├── AirAttackState 空中攻击HitBox 朝正前方激活
├── UpAttackState 上劈HitBox 朝正上方激活
├── DownAttackState 下劈 + OnDownHitConfirmed → trampolineForce 蹦跳反弹
├── HurtState hurtDuration 硬直Initialize(DamageInfo) 注入伤害信息
├── DeadState 冻结 Rigidbody2D触发 _onPlayerDied EventChannelSO
├── ParryState 弹反时序窗口(与 ParrySystem 协作)
├── SpringState 治疗动画;高优先级保护窗口防打断
└── SwimState 液体中自由移动(需解锁 AbilityType.Swim
```
**关键设计决策**
- 状态为 POCO 类,不持有 MonoBehaviour 生命周期开销,也不产生 GCDictionary 在 `Awake` 一次性填充)。
- `PlayerController``TakeDamage` 中先查询 `_currentState.IsInvincible`,后查 `_stats.IsInvincible`(无敌帧窗口),双层保护互不依赖。
- `#if UNITY_EDITOR` 转换白名单在 Editor 模式下帮助捕获非法状态跳转,运行时零开销剔除。
---
### 2.3 数值体系 PlayerStats
```
PlayerStats
├── ISaveable → 存读档SaveManager 调用)
├── IRestoreOnSave → 存档触发时恢复(如灵泉数量)
└── IRewardTarget → RewardSO 颁奖接口(避免 Quest 直接依赖 Player 程序集)
运行时字段
├── HP / MaxHP TakeDamage / Heal / InvincibleTimer
├── SoulPower / Max 法术资源(攻击命中积累)
├── SpiritPower / Max 灵气资源自动回复SpiriRegenTimer 驱动)
├── SpringCharges / Max 灵泉治疗充能槽SpringSystem 消耗)
├── LingZhu 货币(击杀 / 收集 / 购买)
├── AbilityType _unlockedAbilities [Flags] uint 位图HasAbility(flag) O(1) 查询
├── 护符数值修改器
│ ├── _flatModifiers[StatType] 固定值加成(如 +5 MaxHP
│ └── _percentModifiers[StatType] 百分比加成(如 +20% SoulPower
├── AnimatorSpeedMultiplier 1f + _animatorSpeedBonus护符注入攻速
├── SoulCostReduction 法术费用减免(护符叠加)
└── 难度缩放
订阅 DifficultyChangedEventChannel
→ 按当前 HP 比例重算 MaxHP保持 HP 比例不跳变)
```
---
### 2.4 形态系统 Form System
```
FormConfigSO资产Inspector 拖入 FormController
└── FormSO[] forms
├── FormSO { formId="Form_Sky", formType=Sky, defaultWeapon=WeaponSO_SkyBlade }
├── FormSO { formId="Form_Earth", formType=Earth, defaultWeapon=WeaponSO_EarthHammer }
└── FormSO { formId="Form_Death", formType=Death, defaultWeapon=WeaponSO_DeathScythe }
FormController.SwitchForm(FormType)
├─ 1. IntEventChannelSO _onFormChanged.Raise(index)
│ → SaveSystem 持久化 ActiveFormId
│ → UI HUD 更新形态图标
├─ 2. C# event OnFormChanged
│ → WeaponManager.HandleFormChanged() ← OnEnable 订阅OnDisable 退订
└─ 3. VoidEventChannelSO _onSkillSetChanged.Raise()
→ SkillHUD 刷新当前形态技能组图标
```
**护符 Override 流**:护符装备时调用 `WeaponManager.SetOverride(formId, weaponSO)` 覆盖指定形态的默认武器;卸下时调用 `ClearOverride(formId)` 还原,无需修改 `FormSO` 资产。
---
### 2.5 武器系统 Weapon System
```
WeaponSO纯数据 SO
├── 连击动画 attack1/2/3/air/up/downClip Animancer ClipTransition
├── 伤害来源 attack1/2/3/air/up/downSource DamageSourceSO各段独立配置
├── hitBoxPrefab → WeaponHitBoxInstance + HitBox 碰撞体
└── soulPowerGain 命中后灵魂增加量(覆盖默认值)
WeaponManager运行时
│ FormController.OnFormChanged ──►
│ ApplyWeapon(FormSO)
│ ├── 检查 _overrides[formId](护符 Override 优先)
│ └── SetDirectWeapon(WeaponSO)
│ ├── Destroy 旧 HitBox GameObject
│ ├── Instantiate 新 hitBoxPrefab 到 [WeaponSocket]
│ └── OnWeaponChanged.Invoke(newWeapon)
│ └── PlayerCombat 订阅:刷新 _currentHitBoxInstance 引用
PlayerCombat
├── SetComboSegmentSource(comboIndex) ← AttackState 每段开始时调用
│ comboIndex 0/1/2 → attack1/2/3Source → HitBoxInstance.SetDamageSource
├── EnableWeaponHitBox(AttackDirection) ← 动画事件 / State 调用
│ GetSourceByDir → Activate(dir, source, ownerTransform)
└── OnDownHitConfirmed ← DownAttackState 订阅
命中时向上施加 trampolineForce
```
---
### 2.6 技能系统 Skill System
```
FormSkillSOCreateAssetMenu: BaseGames/Skills/FormSkill
├── Identity skillId / displayNameKey / icon
├── Resource resourceTypeSoulPower | SpiritPower/ baseCost / cooldown
├── Animation castAnimationClipTransition/ castLockDuration施放锁定秒数
├── Effect effectTypeMeleeAoE / Projectile / BarrierAura / WraithDash /
│ GroundDive / DragonKick / ShadowDecoy / DelayedExplosion
├── Projectile projectileConfig / isHoming / holdForContinuous
├── Dash dashForce / dashDuration / isInvincibleDuringDash
├── Explosion explosionDelay / explosionRadius
├── Feedback castFeedbackFeedbackPresetSO
└── hitBoxPrefab → 近战/爆炸技能命中盒SkillHitBoxInstance + HitBox
SkillManagerBaseGames.Skills 程序集)
├── FormSkillSO[] _slots 按 SkillSlotNames 枚举索引
├── SkillModifierRegistry _mods 护符注入的冷却/费用修改器
├── float[] _cooldownTimers 每槽独立冷却计时
└── ExecuteSkill(slotIndex)
├── 检查冷却 / 资源baseCost - SoulCostReduction
├── PlayerStats.SpendResource(type, cost)
├── Animancer.Play(castAnimation) + 锁定输入 castLockDuration 秒
└── 依 effectType 分支执行:投射物 / AoE HitBox / Dash / 爆炸延迟 …
```
---
### 2.7 能力解锁 AbilityType Flags
```csharp
[Flags] enum AbilityType : uint
{
None = 0,
// 移动
WallCling = 1u << 0, // 贴墙悬挂
WallJump = 1u << 1, // 墙跳
Dash = 1u << 2, // 地面冲刺
AirDash = 1u << 3, // 空中二段冲刺
DoubleJump = 1u << 4, // 二段跳
SuperJump = 1u << 5, // 聚气超跳
Swim = 1u << 6, // 液体游泳
Dive = 1u << 7, // 下劈
// 法术
Spell1/2/3 = 1u << 8~10,
// 形态
SpiritForm = 1u << 11,
SpiritDash = 1u << 12,
// 战斗
Parry = 1u << 13,
ChargeAttack = 1u << 14,
DownSlash = 1u << 15,
// 互动
Interact = 1u << 16,
FastTravel = 1u << 17,
// 强化
InvincibleDash = 1u << 18, // Dash 无敌帧强化
}
```
- `PlayerStats.HasAbility(flag)` → O(1) 位与运算,无分支列表遍历。
- 状态类在 `OnStateEnter``GetNextState` 中调用 `Stats.HasAbility(AbilityType.WallJump)` 等判断是否允许转换。
- `AbilityManager`Progression 模块)解锁时调用 `PlayerStats.UnlockAbility(flag)` 并写入存档。
---
### 2.8 装备护符系统 Equipment / Charm
```
CharmSO
├── notchCost Notch 槽位消耗量
└── ICharmEffect[] effects
├── OnEquip(EquipmentContext)
│ 可修改PlayerStats 数值 / WeaponManager Override / SkillModifierRegistry
└── OnUnequip(EquipmentContext)
还原所有修改(避免副作用残留)
EquipmentContext注入包Awake 时构建)
├── PlayerStats
├── PlayerFeedback
├── SkillModifierRegistry
└── WeaponManager
EquipmentManagerISaveable
├── _currentNotchCapacity 初始值来自 EquipmentConfigSO可解锁扩容
├── _usedNotches 缓存值(避免每次 LINQ Sum
├── TryEquipCharm(charm) 容量检查 → fx.OnEquip → 事件广播
├── UnequipCharm(charm) fx.OnUnequip → 事件广播
└── 事件频道
├── CharmEventChannelSO _onCharmEquipped
├── CharmEventChannelSO _onCharmUnequipped
└── VoidEventChannelSO _onEquipmentChanged → UI 刷新
```
---
## 3. 小怪Enemy
### 3.1 Scene 节点结构
```
[Enemy_SpiderGuard] ← 根节点(挂 EnemyBase 或具体子类)
│ EnemyBase或 RangedEnemy / FlyingEnemy
│ ├── EnemyStats 运行时 HP / Defense / AttackCooldown
│ │ Initialize(EnemyStatsSO) 注入;难度缩放订阅
│ ├── EnemyMovement Rigidbody2D 封装
│ │ MoveHorizontal / FaceTarget / Knockback / JumpTo
│ ├── EnemyCombat 攻击范围 / 伤害触发(近战/弹幕调度)
│ ├── EnemyFeedback 受击闪烁 / 音效 / HitStop / 受击特效
│ ├── EnemyPoiseComponent IPoiseSource 实现(霸体等级声明)
│ ├── AnimancerComponent
│ ├── BehaviorTree Opsive Behavior Designer 资产绑定
│ └── EnemyNavAgent IPathAgent 实现PathBerserker2D waypoint/jump 寻路)
├── HurtBox isTrigger=trueLayer=EnemyHurtBox
├── HitBox_Melee isTrigger=trueLayer=EnemyHitBox
│ └── HitBox.cs
└── BodyContactDamage可选 碰撞体直接造成接触伤害
```
**子类扩展**
- `RangedEnemy`:额外持有 `ProjectileManager` 引用 / 弹幕发射逻辑覆盖
- `FlyingEnemy`:禁用地面检测,使用独立飞行移动逻辑
---
### 3.2 状态机POCO 状态)
```
EnemyStateType枚举+ Dictionary<EnemyStateType, IEnemyState>
IEnemyState
├── StateType 枚举值(字典键)
├── Enter(EnemyBase owner)
└── Exit(EnemyBase owner)
具体状态
├── EnemyControlledState 正常 AI 驱动Behavior Tree 运行中)
├── EnemyHurtState 受击硬直(播放受击动画,短暂停止 BD
├── EnemyStaggerState 霸体破防强硬直(较长,期间 BD 暂停)
└── EnemyDeadState 死亡IsAlive=false / 关闭碰撞体 / 播放死亡动画 / 掉落战利品)
```
**TakeDamage 伤害判定流**
```
EnemyBase.TakeDamage(DamageInfo)
├── if Dead → return
├── EnemyStats.TakeDamage(finalDamage)
├── EnemyFeedback.OnHit(info) 受击视觉/音效反馈
├── if HP <= 0 → Die()
└── else
├── 比较 info.PoiseBreak vs EnemyPoiseComponent.CurrentPoiseLevel
├── PoiseBreak ≥ CurrentPoise → ForceState(Stagger)
├── PoiseBreak < CurrentPoise → ForceState(Hurt)(仅 Feedback不打断 BD
└── 霸体完全抵抗 → 仅 Feedback受击特效BD 不中断)
```
---
### 3.3 AI — Behavior Designer 节点库
所有 BD 节务类位于 `Assets/_Game/Scripts/Enemies/AI/`,前缀 `BD_`
| 分类 | 任务类 | 功能 |
|------|--------|------|
| **感知** | `BD_IsPlayerVisible` | BatchLOSSystem 查询视线(批量 RaycastBurst 加速) |
| | `BD_IsPlayerInRange` | `EnemyStats.SqrDistanceToPlayer < range²`(避免 sqrt |
| | `BD_IsHPBelow` | `EnemyStats.CurrentHP / MaxHP < ratio` |
| | `BD_IsNearEdge` | 边缘检测(防坠落巡逻) |
| | `BD_IsGrounded` | 地面状态查询 |
| | `BD_IsStateMatch` | 查询当前 EnemyStateType |
| **移动** | `BD_MoveTo` | 目标点直线移动EnemyNavAgent |
| | `BD_MoveToPlayer` | 追击玩家位置 |
| | `BD_Patrol` | 往返巡逻PatrolPoints[] 路径点) |
| | `BD_JumpTo` | 抛物线跳跃到目标位置 |
| | `BD_TeleportTo` | 瞬移Boss 阶段过渡用) |
| | `BD_StopMovement` | 停止水平速度 |
| | `BD_FaceTarget` | 朝向玩家/目标 |
| **战斗** | `BD_Attack` | 触发近战攻击EnemyCombat |
| | `BD_CanAttack` | 攻击冷却检查AttackCooldownTimer <= 0 |
| | `BD_SpawnProjectile` | 生成投射物ProjectileManager |
| | `BD_TelegraphAttack` | 激活 TelegraphSystem 预兆提示 |
| **特殊** | `BD_SummonMinions` | 召唤小怪Boss 用) |
| | `BD_EnterPhase` | 调用 BossBase.EnterPhase(phase) |
| | `BD_SetAlert` | 设置警觉状态标记(影响巡逻/追击切换) |
| **动画** | `BD_PlayAnimation` | Animancer 播放指定 Clip |
| | `BD_WaitForAnimation` | 等待当前动画播放完毕 |
| **时序** | `BD_Wait` | 等待固定秒数 |
| | `BD_WaitRandom` | 等待随机时长min~max |
`BatchLOSSystem`:单例系统,每帧收集所有 `ILOSRequester` 的视线查询,批量执行 Raycast可选 Burst Job结果写回各敌人缓存避免 N 个敌人同帧各自独立 Physics2D.Raycast 的性能峰值。
---
## 4. Boss
### 4.1 继承关系
```
MonoBehaviour
└── EnemyBaseIDamageable / ILOSRequester
└── BossBase
├── 多阶段切换EnterPhase(int) + BossPhaseEventChannelSO 广播
├── IsHPBelow(float ratio) → BD_IsHPBelow 轮询条件
└── override Die() → _onBossFightEnded.Raise(true)
└── [具体 Boss 类]
override EnterPhase → 额外过渡逻辑(动画/无敌帧/BD 子树切换)
```
---
### 4.2 Scene 节点结构
```
[Boss_XxxGuardian]
│ BossBase具体 Boss 脚本,继承 BossBase
│ ├── EnemyStats / EnemyMovement / EnemyCombat / EnemyFeedback
│ ├── BossSkillExecutor 接收 BD/Orchestrator 指令,执行 BossSkillSO 协程
│ ├── WeakPointSystem 弱点激活窗口管理BossSkillExecutor 技能后开启)
│ ├── TelegraphSystem 攻击预兆提示(激光标线 / 范围高亮 / 地面警示)
│ ├── BehaviorTree 含 BD_EnterPhase 的行为树资产
│ └── AnimancerComponent
├── HurtBox 主体受击盒Layer=EnemyHurtBox
├── WeakPoint_Head 弱点受击盒
│ └── HurtBox弱点专属WeakPointSystem 控制激活/关闭)
├── HitBox_Slam 近战攻击 HitBoxLayer=EnemyHitBox
├── HitBox_Sweep 横扫 HitBox可与 BossSkillSO 绑定)
└── BossArenaBlocker可选 竞技场封锁触发器Boss 战开始时封门)
```
---
### 4.3 技能执行流 BossSkillSO + BossSkillExecutor
```
BossSkillSOCreateAssetMenu: BaseGames/Boss/BossSkill
├── skillId / displayName
├── BossSkillType枚举
├── AttackPatternSO
│ ├── DamageSourceDamageSourceSO
│ ├── KnockbackAngle
│ ├── 弹幕参数ProjectilePrefab / Count / SpreadAngle / Speed
│ ├── AoE 参数Radius / Offset
│ └── 时序WindupDuration / ActiveDuration / RecoveryDuration
├── VulnerabilityWindowDuration 技能结束后弱点暴露时长(秒)
└── SkillSequenceSO可选 组合技序列(按顺序或随机排列多个 BossSkillSO
BossSkillExecutor.ExecuteSkill(BossSkillSO)
│ if _isExecuting → return
└── StartCoroutine(ExecuteSkillCoroutine)
├── _onBossSkillStarted.Raise(BossSkillEvent)
├── TelegraphSystem.ShowTelegraph(skill.pattern) 预兆提示激活
├── WaitForSeconds(WindupDuration) 前摇等待
├── 激活 HitBox[] / ProjectileManager.Spawn(pattern) 伤害输出
├── WaitForSeconds(ActiveDuration) 活跃帧等待
├── 关闭 HitBox / 清理弹幕
├── WeakPointSystem.OpenWindow(VulnerabilityWindowDuration) 弱点窗口
├── WaitForSeconds(RecoveryDuration) 后摇等待
└── _onBossSkillEnded.Raise(BossSkillEvent)
WaitForSeconds 缓存:
static Dictionary<float, WaitForSeconds> _wfsCache
[RuntimeInitializeOnLoadMethod] ClearWFSCache()
→ 避免协程每次 new WaitForSeconds 的 GC 分配
```
**InterruptCurrentSkill()**:阶段切换时强制停止当前协程并调用 `FinishExecution()`,确保状态一致性。
---
### 4.4 阶段切换
```
BD_IsHPBelow每帧轮询
└── BossBase.IsHPBelow(ratio) = CurrentHP / MaxHP < ratio
→ true 时 BD 子树激活 BD_EnterPhase
BD_EnterPhase → BossBase.EnterPhase(phase)
├── _currentPhase = phase
├── BossPhaseEventChannelSO _onBossPhaseChanged.Raise(BossPhaseEvent{BossId, Phase})
│ → Boss HP 条分段动画UI
│ → 音乐系统切换 BGM 段落
│ → VFX 场景效果触发
└── [子类重写 EnterPhase]
├── BossSkillExecutor.InterruptCurrentSkill() 打断当前技能
├── 切换 BD 行为树活跃子树(换招式库)
├── 播放阶段过渡动画Animancer
└── 短暂无敌帧(保护阶段切换不被秒杀)
```
---
## 5. 共享战斗层 Combat Module
### 5.1 核心接口
| 接口 | 实现者 | 用途 |
|------|--------|------|
| `IDamageable` | `PlayerController` / `EnemyBase` | HurtBox 统一调用入口,解耦具体角色类型 |
| `IPoiseSource` | `PlayerController`(返回 None/ `EnemyPoiseComponent` | 霸体等级声明TakeDamage 中比较 |
| `IShieldable` | `ShieldComponent`(玩家专属) | 伤害先经护盾吸收,剩余量才走 TakeDamage |
| `IStatusEffectable` | `StatusEffectManager` | 状态效果施加入口Combat 程序集不直接引用 StatusEffects |
| `IBreakable` | 可破坏机关 / 障碍物 | HitBox 命中非 HurtBox 对象时的分支处理 |
| `IPathAgent` | `EnemyNavAgent` | EnemyBase 通过接口引用导航,避免对 Navigation 程序集的直接依赖 |
---
### 5.2 HitBox → HurtBox 伤害流水线
```
HitBox.OnTriggerEnter2D(Collider2D other)
├── 1. Layer 白名单过滤(仅命中 EnemyHurtBox / PlayerHurtBox
├── 2. _alreadyHit HashSet 防重复命中(同次激活期间)
├── 3. other.GetComponentInParent<HurtBox>() 获取受击盒
└── HurtBox.ReceiveDamage(DamageInfo)
├── 1. IsAlive 检查
├── 2. IDamageable.IsInvincible 检查
│ (冲刺无敌帧 / DeadState / Stats.InvincibleTimer
├── 3. IShieldable.AbsorbDamage(amount)
│ 护盾优先吸收,返回穿透量
├── 4. IPoiseSource 霸体等级比较
│ DamageInfo.PoiseBreakLevel vs GetCurrentPoiseLevel()
├── 5. DamageInfo.FinalDamage 计算(基础 - Defense
├── 6. IStatusEffectable.ApplyStatusEffect(DamageType)
Fire → FireEffect / Poison → PoisonEffect
├── 7. IDamageable.TakeDamage(info)
│ → PlayerController / EnemyBase 状态机转换
└── 8. HitConfirmedEventChannelSO.Raise(HitInfo)
→ HUD 命中提示 / 灵魂增加 / HitStop 触发
```
---
### 5.3 状态效果系统
```
StatusEffectManagerIStatusEffectable
├── ApplyStatusEffect(DamageType type)
│ → 查找或创建对应 StatusEffect 实例并激活
├── FireEffect 持续 DoTTick 扣 HP/ 视觉火焰 VFX
├── PoisonEffect 持续 DoT + 移动速度降低(可叠加层数)
└── StaggerEffect 触发 EnemyStaggerState / 破霸体
StatusEffectEventChannelSO 广播效果开始/结束UI 状态图标)
```
---
## 6. 数据驱动 ScriptableObject 体系
| SO 类型 | 所属程序集 | 用途 |
|---------|-----------|------|
| `PlayerStatsSO` | `BaseGames.Player` | 玩家初始数值、最大值配置 |
| `PlayerMovementConfigSO` | `BaseGames.Player` | 移动速度/加速/跳跃力/冲刺参数等 |
| `PlayerAnimationConfigSO` | `BaseGames.Player` | 各状态动画 ClipTransition 集合 |
| `FormConfigSO` / `FormSO` | `BaseGames.Player` | 形态列表 + 各形态默认武器 |
| `WeaponSO` | `BaseGames.Player` | 武器连击动画/伤害来源/HitBox Prefab |
| `FormSkillSO` | `BaseGames.Skills` | 技能全量配置(动画/资源/效果/HitBox |
| `CharmSO` / `EquipmentConfigSO` | `BaseGames.Equipment` | 护符效果列表 + Notch 容量初始值 |
| `DamageSourceSO` | `BaseGames.Combat` | 伤害值/类型/霸体破防等级/击退参数 |
| `ProjectileConfigSO` | `BaseGames.Combat` | 投射物速度/碰撞层/生命时长/弹幕参数 |
| `EnemyStatsSO` | `BaseGames.Enemies` | 敌人 HP/Defense/速度/攻击冷却 |
| `EnemyAnimationConfigSO` | `BaseGames.Enemies` | 敌人动画 Clip 集合 |
| `AttackPatternSO` | `BaseGames.Enemies`Boss | 攻击图案:伤害/弹幕/AoE/时序 |
| `BossSkillSO` | `BaseGames.Enemies`Boss | Boss 技能全量配置 |
| `SkillSequenceSO` | `BaseGames.Enemies`Boss | Boss 组合技序列(有序/随机) |
| `BossResourceConfigSO` | `BaseGames.Enemies`Boss | Boss 阶段资源HP 阈值/技能池) |
**设计原则**:所有运行时组件在 `Awake` 中通过 `Initialize(SO)` 接收配置,与数据资产完全解耦,支持 Inspector 热替换和难度 A/B 测试,无需修改脚本代码。
---
## 7. 架构核心原则总结
| 原则 | 具体体现 |
|------|---------|
| **单一职责** | 移动 / 数值 / 战斗 / 动画各为独立 MonoBehaviour`PlayerController` 仅负责 FSM 协调,不持有业务逻辑 |
| **事件驱动** | `EventChannelSO`(广播,跨程序集零直接引用)+ C# event点对点同程序集高频回调双轨并行 |
| **数据与逻辑分离** | 所有配置数据存入 ScriptableObject运行时组件只持有 SO 引用,数值修改在 SO 层完成 |
| **接口隔离** | `IDamageable / IPoiseSource / IShieldable / IStatusEffectable / IBreakable / IPathAgent` 六大接口隔离具体实现 |
| **状态不继承 MB** | `PlayerStateBase` 为 POCO 类,生命周期由 `PlayerController` 驱动,无 GC 开销 |
| **能力位图** | `AbilityType [Flags] uint` 支持任意组合查询O(1) 位与运算,无枚举列表遍历 |
| **难度热切换** | `EnemyStats` / `PlayerStats` 均订阅 `DifficultyChangedEventChannel`,保持 HP 比例重算,运行时切换零重置 |
| **护符副作用隔离** | `ICharmEffect.OnEquip / OnUnequip` 配对调用,每个效果负责自身还原,`EquipmentManager` 不持有修改记录 |
| **GC 意识** | `WaitForSeconds` 协程缓存、`_alreadyHit HashSet` 复用、`SqrDistanceToPlayer`(避免 sqrt`BatchLOSSystem` 批量 Raycast |
| **执行顺序管控** | `PlayerMovement -200``PlayerController -100` → 其余默认 0确保物理写入先于状态机读取 |