Files
Emberwild/Assets/GAME/Script/UI/DeathScreen.cs
T
2026-06-22 16:18:34 +02:00

132 lines
3.9 KiB
C#

using UnityEngine;
using UnityEngine.UI;
using Ashwild.Player;
namespace Ashwild.UI
{
public class DeathScreen : MonoBehaviour
{
[Header("Timing")]
[SerializeField] private float fadeDelay = 0.8f;
[SerializeField] private float fadeDuration = 1.5f;
[SerializeField] private float respawnDelay = 1f;
[Header("UI")]
[SerializeField] private Image fadeOverlay;
private PlayerLifecycle playerLifecycle;
private bool isDying;
private float timer;
private enum Phase { Wait, Fade, Black, Done }
private Phase phase;
private bool bound;
/// <summary>
/// Waits for the networked local player to spawn before hooking onto its death event.
/// </summary>
private void OnEnable()
{
PlayerEvents.LocalPlayerSpawned += HandleLocalPlayerSpawned;
}
/// <summary>
/// Unsubscribes — mirrors OnEnable exactly.
/// </summary>
private void OnDisable()
{
PlayerEvents.LocalPlayerSpawned -= HandleLocalPlayerSpawned;
}
private void Start()
{
if (fadeOverlay != null)
{
fadeOverlay.color = Color.clear;
fadeOverlay.raycastTarget = false;
}
// The player may already exist (late UI init); otherwise we wait for the spawn event.
if (PlayerStats.Instance != null)
BindToPlayer();
}
/// <summary>
/// Binds to the local player as soon as it spawns on the network.
/// </summary>
private void HandleLocalPlayerSpawned() => BindToPlayer();
/// <summary>
/// Caches the lifecycle and listens for the local player's death; runs once.
/// </summary>
private void BindToPlayer()
{
if (bound) return;
if (PlayerStats.Instance == null) return;
bound = true;
// Take the lifecycle from the LOCAL player only. A global Find would also match remote
// players (their root GameObject stays active; only the Behaviour is disabled), and could
// respawn the wrong player in multiplayer.
playerLifecycle = PlayerStats.Instance.GetComponent<PlayerLifecycle>();
PlayerStats.Instance.onDeath.AddListener(OnDeath);
}
private void OnDeath()
{
if (isDying) return;
isDying = true;
timer = 0f;
phase = Phase.Wait;
}
private void Update()
{
if (!isDying) return;
timer += Time.deltaTime;
switch (phase)
{
case Phase.Wait:
if (timer >= fadeDelay)
{
phase = Phase.Fade;
timer = 0f;
}
break;
case Phase.Fade:
float fadeT = Mathf.Clamp01(timer / fadeDuration);
if (fadeOverlay != null)
fadeOverlay.color = new Color(0f, 0f, 0f, fadeT);
if (fadeT >= 1f)
{
phase = Phase.Black;
timer = 0f;
}
break;
case Phase.Black:
if (timer >= respawnDelay)
{
playerLifecycle.Respawn();
if (fadeOverlay != null)
fadeOverlay.color = Color.clear;
isDying = false;
phase = Phase.Done;
}
break;
}
}
private void OnDestroy()
{
if (PlayerStats.Instance != null)
PlayerStats.Instance.onDeath.RemoveListener(OnDeath);
}
}
}