按阶段启停能力组件,被禁用的招经 CanUse 自动退出选招候选, 阶段门不需要碰选招器。取代 BossSkillSO.availablePhaseIndices。 EnterPhase 先换池后广播;OnSpawn 回阶段 0(对象池复用)。
62 lines
2.3 KiB
C#
62 lines
2.3 KiB
C#
using System;
|
||
using UnityEngine;
|
||
using BaseGames.Enemies.Abilities;
|
||
|
||
namespace BaseGames.Enemies
|
||
{
|
||
/// <summary>
|
||
/// 阶段 = 换招池:按当前阶段启用 / 禁用能力组件。
|
||
/// 被禁用的能力其 <see cref="EnemyAbilityBase.CanUse"/> 为 false,
|
||
/// 因此自动从 <see cref="EnemyAttackSelector"/> 的候选里消失——阶段门不需要碰选招器。
|
||
///
|
||
/// 由 <see cref="BossBase.EnterPhase"/> 与 <see cref="BossBase.OnSpawn"/> 直接调用
|
||
/// (而非订阅阶段频道),保证与阶段切换严格同序。
|
||
/// </summary>
|
||
public sealed class BossPhaseAbilityGate : MonoBehaviour
|
||
{
|
||
[Serializable]
|
||
public struct PhaseEntry
|
||
{
|
||
[Tooltip("受阶段管控的能力组件")]
|
||
public EnemyAbilityBase ability;
|
||
[Tooltip("该能力可用的阶段索引;空数组 = 全阶段可用")]
|
||
public int[] phases;
|
||
}
|
||
|
||
[Tooltip("阶段可用性表。未登记的能力不受本组件影响(保持其自身启用状态)")]
|
||
[SerializeField] private PhaseEntry[] _entries;
|
||
|
||
/// <summary>把指定阶段的启用集应用到所有登记的能力。</summary>
|
||
public void ApplyPhase(int phase)
|
||
{
|
||
if (_entries == null) return;
|
||
for (int i = 0; i < _entries.Length; i++)
|
||
{
|
||
var e = _entries[i];
|
||
if (e.ability == null) continue;
|
||
e.ability.enabled = IsAllowed(e.phases, phase);
|
||
}
|
||
}
|
||
|
||
private static bool IsAllowed(int[] phases, int phase)
|
||
{
|
||
if (phases == null || phases.Length == 0) return true; // 空 = 全阶段
|
||
for (int i = 0; i < phases.Length; i++)
|
||
if (phases[i] == phase) return true;
|
||
return false;
|
||
}
|
||
|
||
#if UNITY_EDITOR
|
||
// 漏配显式报错,不静默跳过(CLAUDE.md 第 6 条)
|
||
private void OnValidate()
|
||
{
|
||
if (_entries == null) return;
|
||
for (int i = 0; i < _entries.Length; i++)
|
||
if (_entries[i].ability == null)
|
||
Debug.LogError(
|
||
$"[BossPhaseAbilityGate] {name} 第 {i} 项未指定能力组件,该行不会生效。", this);
|
||
}
|
||
#endif
|
||
}
|
||
}
|