重构
This commit is contained in:
@@ -2,13 +2,23 @@ using UnityEngine;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using GameFramework;
|
||||
using Architecture.Core;
|
||||
using Architecture.Variables;
|
||||
|
||||
namespace IndianOceanAssets.Engine2_5D
|
||||
{
|
||||
// Handles health, damage, and death for entities
|
||||
public class HealthSystem : MonoBehaviour
|
||||
{
|
||||
/// <summary>玩家受伤时触发(用于受击特效等)</summary>
|
||||
public static Action onPlayerDamaged;
|
||||
[Header("SO 事件通道(替代 static onPlayerDamaged 事件)")]
|
||||
[SerializeField] private GameEvent onPlayerDamagedEvent;
|
||||
|
||||
[Header("SO 事件通道(玩家死亡,替代直接调用 GameManager.GameOver)")]
|
||||
[SerializeField] private GameEvent onPlayerDiedEvent;
|
||||
|
||||
[Header("SO 变量(供 EnemyHealthBar / HUD 订阅,替代反射读取私有字段)")]
|
||||
[SerializeField] private IntVariable healthVar;
|
||||
[SerializeField] private IntVariable maxHealthVar;
|
||||
|
||||
[Range(1, 100)]
|
||||
[SerializeField]
|
||||
@@ -31,6 +41,7 @@ namespace IndianOceanAssets.Engine2_5D
|
||||
private bool _isDead = false; // 防止重复触发死亡
|
||||
private bool _isInvincible = false; // 无敌状态
|
||||
private float _invincibleTimer = 0f; // 无敌剩余时间(<=0 表示永久无敌)
|
||||
private bool _warnedDamaged = false; // 防止 onPlayerDamagedEvent 空引用告警刷屏
|
||||
|
||||
[Header("受伤无敌")]
|
||||
[Tooltip("玩家受伤后的无敌时间(秒)")]
|
||||
@@ -42,13 +53,33 @@ namespace IndianOceanAssets.Engine2_5D
|
||||
/// <summary>是否处于无敌状态(只读)</summary>
|
||||
public bool IsInvincible => _isInvincible;
|
||||
|
||||
/// <summary>当前血量(只读)</summary>
|
||||
public int CurrentHealth => health;
|
||||
|
||||
/// <summary>最大血量(只读)</summary>
|
||||
public int MaxHealth => maxHealth;
|
||||
|
||||
/// <summary>血量变化事件(current, max)。敌人血条等本地订阅者用于刷新显示,替代反射读取私有字段。</summary>
|
||||
public event System.Action<int, int> OnHealthChanged;
|
||||
|
||||
// 编辑器实时校验:事件字段未接线时给出黄色警告三角 + 控制台告警
|
||||
private void OnValidate()
|
||||
{
|
||||
if (isPlayer && onPlayerDamagedEvent == null)
|
||||
Debug.LogWarning($"[HealthSystem] 玩家 HealthSystem 的 On Player Damaged Event 未接线({gameObject.name})。受击泛红不会出现。", this);
|
||||
if (isPlayer && onPlayerDiedEvent == null)
|
||||
Debug.LogWarning($"[HealthSystem] 玩家 HealthSystem 的 On Player Died Event 未接线({gameObject.name})。玩家死亡不会触发过场。", this);
|
||||
}
|
||||
|
||||
// Initializes health
|
||||
private void Start()
|
||||
{
|
||||
health = maxHealth;
|
||||
if (isPlayer)
|
||||
{
|
||||
if (maxHealthVar != null) maxHealthVar.Value = maxHealth;
|
||||
if (healthVar != null) healthVar.Value = health;
|
||||
}
|
||||
}
|
||||
|
||||
// Applies damage and checks for death
|
||||
@@ -58,10 +89,20 @@ namespace IndianOceanAssets.Engine2_5D
|
||||
if (_isInvincible) return; // 无敌状态,免疫伤害
|
||||
|
||||
health -= damageAmount;
|
||||
if (isPlayer && healthVar != null) healthVar.Value = health;
|
||||
OnHealthChanged?.Invoke(health, maxHealth);
|
||||
|
||||
// 玩家受伤时触发事件(用于受击泛红特效)
|
||||
if (isPlayer && onPlayerDamaged != null)
|
||||
onPlayerDamaged.Invoke();
|
||||
if (isPlayer)
|
||||
{
|
||||
if (onPlayerDamagedEvent != null)
|
||||
onPlayerDamagedEvent.Raise();
|
||||
else if (!_warnedDamaged)
|
||||
{
|
||||
Debug.LogWarning("[HealthSystem] onPlayerDamagedEvent 未接线!受击泛红特效不会触发。请在玩家 HealthSystem 的 On Player Damaged Event 字段拖入 OnPlayerDamaged 资产。", this);
|
||||
_warnedDamaged = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 播放受伤音效
|
||||
if (isPlayer && AudioManager.Instance != null)
|
||||
@@ -78,8 +119,8 @@ namespace IndianOceanAssets.Engine2_5D
|
||||
|
||||
if (isPlayer)
|
||||
{
|
||||
// 玩家死亡:触发过场动画,不立即销毁(由 GameManager 处理)
|
||||
GameManager.GameOver();
|
||||
// 玩家死亡:通过 OnPlayerDied SO 事件通知 GameManager(解耦,不再直接调用单例)
|
||||
onPlayerDiedEvent?.Raise();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -213,4 +254,4 @@ namespace IndianOceanAssets.Engine2_5D
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user