diff --git a/Assets/_Game/Scripts/Enemies/Boss/BossFightTrigger.cs b/Assets/_Game/Scripts/Enemies/Boss/BossFightTrigger.cs
new file mode 100644
index 00000000..b6a492d9
--- /dev/null
+++ b/Assets/_Game/Scripts/Enemies/Boss/BossFightTrigger.cs
@@ -0,0 +1,96 @@
+using UnityEngine;
+using BaseGames.AI;
+using BaseGames.Core.Events;
+
+namespace BaseGames.Enemies
+{
+ ///
+ /// Boss 开战触发:玩家进入竞技场触发区时,广播开战事件并让 Boss 的决策层从静置态进战。
+ /// 此前开战事件频道全项目零发送方,Boss 永远不会开战。
+ ///
+ /// 放在 Boss 房间入口的触发区上(Collider2D + isTrigger)。只触发一次。
+ /// 漏配一律在 Awake 显式报错——静默不触发会表现为"Boss 站着不动",极难定位。
+ ///
+ [RequireComponent(typeof(Collider2D))]
+ public sealed class BossFightTrigger : MonoBehaviour
+ {
+ [Header("目标 Boss")]
+ [Tooltip("要唤醒的 Boss 的决策层组件")]
+ [SerializeField] private EnemyAiBrain _bossBrain;
+
+ [Header("事件频道")]
+ [Tooltip("EVT_BossFightStarted — payload 为 bossId,驱动全局状态机 / 后处理 / HUD")]
+ [SerializeField] private StringEventChannelSO _onBossFightStarted;
+ [Tooltip("EVT_BossFightEnded — 布尔开关频道,true 表示开始,驱动 Boss 血条与 BGM 切换")]
+ [SerializeField] private BoolEventChannelSO _onBossFightToggled;
+
+ [Header("标识")]
+ [Tooltip("Boss id,与 Boss 身上配置的 bossId 一致")]
+ [SerializeField] private string _bossId;
+
+ [Header("触发条件")]
+ [Tooltip("玩家所在的层")]
+ [SerializeField] private LayerMask _playerLayers;
+
+ private bool _fired;
+
+ // 漏配处理沿用 EnemyAiBrain 的形态:逐条点名报错 + 停用组件。
+ // 不做「缺谁就跳过谁」的部分执行——半开的战斗(有 BGM 没血条、Boss 不动)
+ // 比彻底不开更难查,问题必须停在配置这一层。
+ private void Awake()
+ {
+ bool valid = true;
+
+ var col = GetComponent();
+ if (!col.isTrigger)
+ {
+ Debug.LogError($"[BossFightTrigger] {name} 的 Collider2D 未勾选 Is Trigger,无法触发开战。", this);
+ valid = false;
+ }
+ if (_bossBrain == null)
+ {
+ Debug.LogError($"[BossFightTrigger] {name} 未指定目标 Boss 的 EnemyAiBrain,开战不会生效。", this);
+ valid = false;
+ }
+ if (string.IsNullOrEmpty(_bossId))
+ {
+ Debug.LogError($"[BossFightTrigger] {name} 未填 bossId,BGM / 血条无法定位该 Boss。", this);
+ valid = false;
+ }
+ if (_onBossFightStarted == null)
+ {
+ Debug.LogError($"[BossFightTrigger] {name} 未绑定开战事件频道,全局状态机 / 后处理不会响应开战。", this);
+ valid = false;
+ }
+ if (_onBossFightToggled == null)
+ {
+ Debug.LogError($"[BossFightTrigger] {name} 未绑定开战开关频道,Boss 血条与战斗 BGM 不会切换。", this);
+ valid = false;
+ }
+ // 掩码为空 = 任何层都过不了下面的判定,触发区形同虚设。
+ if (_playerLayers.value == 0)
+ {
+ Debug.LogError($"[BossFightTrigger] {name} 的玩家层掩码为空,触发区永远不会被触发。", this);
+ valid = false;
+ }
+
+ if (!valid) enabled = false;
+ }
+
+ // 能走到这里说明 Awake 的配置校验全过了,故不再判空——
+ // 判空只会把已经报过错的漏配再盖一层。
+ private void OnTriggerEnter2D(Collider2D other)
+ {
+ if (_fired) return;
+ if ((_playerLayers.value & (1 << other.gameObject.layer)) == 0) return;
+
+ _fired = true;
+ _onBossFightStarted.Raise(_bossId);
+ _onBossFightToggled.Raise(true);
+ _bossBrain.Send(AiSignal.Engaged);
+ }
+
+ /// 供存档回载 / 重试时复位(Boss 未被击败则重新可触发)。
+ public void ResetTrigger() => _fired = false;
+ }
+}
diff --git a/Assets/_Game/Scripts/Enemies/Boss/BossFightTrigger.cs.meta b/Assets/_Game/Scripts/Enemies/Boss/BossFightTrigger.cs.meta
new file mode 100644
index 00000000..1438cefb
--- /dev/null
+++ b/Assets/_Game/Scripts/Enemies/Boss/BossFightTrigger.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: bd8a9d00a149c124a9bd90ffba663a32
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant: