using UnityEngine; using System; using System.Collections; using GameFramework; namespace IndianOceanAssets.Engine2_5D { // Handles health, damage, and death for entities public class HealthSystem : MonoBehaviour { /// 玩家受伤时触发(用于受击特效等) public static Action onPlayerDamaged; [Range(1, 100)] [SerializeField] private int maxHealth = 5; // Maximum health private int health = 5; // Current health [SerializeField] private GameObject deathEffect; // Effect prefab on death [SerializeField] private bool isPlayer; // Is this the player? [Header("消隐特效")] [Tooltip("死亡消隐使用的溶解材质(Custom/SpriteDissolve shader)")] [SerializeField] private Material dissolveMaterial; [Tooltip("消隐动画持续时间(秒)")] [SerializeField] private float fadeDuration = 2f; private bool _isDead = false; // 防止重复触发死亡 /// 是否已死亡(只读) public bool IsDead => _isDead; /// 最大血量(只读) public int MaxHealth => maxHealth; // Initializes health private void Start() { health = maxHealth; } // Applies damage and checks for death public void Damage(int damageAmount) { if (_isDead) return; // 已死亡,不再处理 health -= damageAmount; // 玩家受伤时触发事件(用于受击泛红特效) if (isPlayer && onPlayerDamaged != null) onPlayerDamaged.Invoke(); // 播放受伤音效 if (isPlayer && AudioManager.Instance != null) AudioManager.Instance.PlaySFXFromResources("SFX/Hurt", 0.7f); // If dead if (health <= 0) { _isDead = true; if (isPlayer) { // 玩家死亡:触发过场动画,不立即销毁(由 GameManager 处理) GameManager.GameOver(); } else { // 非玩家:正常播放死亡特效并销毁 Die(); } } } // Handles death logic and effects public void Die() { if (deathEffect != null) Instantiate(deathEffect, transform.position + new Vector3(0f, .5f, 0f), Quaternion.identity); // 如果有溶解材质,播放消隐动画后再销毁 if (dissolveMaterial != null) { StartCoroutine(DissolveAndDestroy()); } else { Destroy(gameObject); } } /// /// 溶解消隐协程:切换材质 → 禁用碰撞/AI → 动画溶解 → 销毁。 /// private IEnumerator DissolveAndDestroy() { // 禁用碰撞体和刚体,防止死亡过程中仍能触发碰撞或受重力下坠 foreach (var col in GetComponents()) col.enabled = false; foreach (var col in GetComponents()) col.enabled = false; foreach (var rb in GetComponents()) rb.isKinematic = true; foreach (var rb in GetComponents()) rb.isKinematic = true; // 禁用所有 MonoBehaviour(AI、动画等),防止死亡后仍移动/攻击 foreach (var mb in GetComponents()) { if (mb != this) mb.enabled = false; } // 切换所有 SpriteRenderer 到溶解材质 var renderers = GetComponentsInChildren(); var originalMats = new Material[renderers.Length][]; for (int i = 0; i < renderers.Length; i++) { originalMats[i] = renderers[i].materials; renderers[i].materials = new Material[] { new Material(dissolveMaterial) }; } // 动画溶解 float elapsed = 0f; while (elapsed < fadeDuration) { elapsed += Time.deltaTime; float t = Mathf.Clamp01(elapsed / fadeDuration); for (int i = 0; i < renderers.Length; i++) { if (renderers[i] != null && renderers[i].material != null) renderers[i].material.SetFloat("_DissolveAmount", t); } yield return null; } Destroy(gameObject); } } }