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

30 KiB
Raw Permalink Blame History

25 · 角色系统架构全景图

命名空间 BaseGames.PlayerBaseGames.Player.StatesBaseGames.EnemiesBaseGames.Enemies.AIBaseGames.BossBaseGames.Combat
路径 Assets/_Game/Scripts/Player/Assets/_Game/Scripts/Enemies/Assets/_Game/Scripts/Combat/
关联文档 05_PlayerModule · 06_CombatModule · 07_EnemyModule · 09_ProgressionModule · 23_BossSkillModule
建立日期 2026-05-17

本文档是跨模块的角色系统实现全景图,侧重三类角色(玩家 / 小怪 / Boss在 Scene 中的节点结构、脚本职责划分、子系统数据流与相互协作关系。各模块深度细节请参阅上方关联文档。


目录

  1. 程序集依赖总览
  2. 玩家Player
  3. 小怪Enemy
  4. Boss
  5. 共享战斗层 Combat Module
  6. 数据驱动 ScriptableObject 体系
  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 仅依赖 CorePlayer / Enemies 均依赖 Combat 而不互相依赖。跨层通信一律通过 EventChannelSOServiceLocator 完成。


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> 状态字典,每帧驱动 _currentStateOnStateUpdate / 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 一次性填充)。
  • PlayerControllerTakeDamage 中先查询 _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

[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) 位与运算,无分支列表遍历。
  • 状态类在 OnStateEnterGetNextState 中调用 Stats.HasAbility(AbilityType.WallJump) 等判断是否允许转换。
  • AbilityManagerProgression 模块)解锁时调用 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.EnemiesBoss 攻击图案:伤害/弹幕/AoE/时序
BossSkillSO BaseGames.EnemiesBoss Boss 技能全量配置
SkillSequenceSO BaseGames.EnemiesBoss Boss 组合技序列(有序/随机)
BossResourceConfigSO BaseGames.EnemiesBoss Boss 阶段资源HP 阈值/技能池)

设计原则:所有运行时组件在 Awake 中通过 Initialize(SO) 接收配置,与数据资产完全解耦,支持 Inspector 热替换和难度 A/B 测试,无需修改脚本代码。


7. 架构核心原则总结

原则 具体体现
单一职责 移动 / 数值 / 战斗 / 动画各为独立 MonoBehaviourPlayerController 仅负责 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(避免 sqrtBatchLOSSystem 批量 Raycast
执行顺序管控 PlayerMovement -200PlayerController -100 → 其余默认 0确保物理写入先于状态机读取