269 lines
9.0 KiB
C#
269 lines
9.0 KiB
C#
using UnityEngine;
|
||
using DG.Tweening;
|
||
|
||
public enum DeathType { Normal, Laser, Spikes }
|
||
|
||
public class Skywalker_GameManager : MonoBehaviour
|
||
{
|
||
public static Skywalker_GameManager Instance;
|
||
|
||
[Header("UI References")]
|
||
public GameObject gameOverPanel;
|
||
|
||
[Header("Player Reference")]
|
||
public Skywalker_PlayerController player; // assign in inspector
|
||
|
||
[Header("Heaven Tween")]
|
||
public float heavenHeight = 4f; // ascent height
|
||
public float ascendDuration = 2.5f; // ascent time
|
||
public float fadeDelay = 2.0f; // wait before fade (2–3s)
|
||
public float fadeDuration = 0.5f; // fade to 1
|
||
|
||
[Header("Material (AllIn1SpriteShader)")]
|
||
public Material playerMaterial;
|
||
|
||
private bool isGameOver = false;
|
||
|
||
// AllIn1SpriteShader property IDs
|
||
static readonly int ID_FadeAmount = Shader.PropertyToID("_FadeAmount");
|
||
static readonly int ID_FadeBurnWidth = Shader.PropertyToID("_FadeBurnWidth");
|
||
|
||
// AllIn1SpriteShader keywords
|
||
const string KW_FADE = "FADE_ON";
|
||
const string KW_GREYSCALE = "GREYSCALE_ON";
|
||
const string KW_GHOST = "GHOST_ON";
|
||
const string KW_OVERLAY = "OVERLAY_ON";
|
||
const string KW_OVERLAYMULT = "OVERLAYMULT_ON"; // we'll keep this OFF unless you want multiply overlay
|
||
|
||
// store original keyword states so we can restore on disable
|
||
bool origFade, origGrey, origGhost, origOverlay, origOverlayMult;
|
||
|
||
Sequence deathSeq;
|
||
// --- Blueberry Glow Pulse (AllIn1SpriteShader) ---
|
||
[Header("Blueberry Glow Pulse")]
|
||
public Material glowMaterial; // optional: defaults to playerMaterial if null
|
||
[Tooltip("Shader float property for glow intensity (AllIn1SpriteShader).")]
|
||
public string glowIntensityProp = "_GlowIntensity"; // change to your exact prop name if different
|
||
public float glowBase = 1.75f;
|
||
public float glowPeak = 7.75f;
|
||
public float glowPulseDuration = 0.6f; // total time (up + down)
|
||
|
||
private Sequence glowSeq;
|
||
private int _ID_GlowIntensity;
|
||
private string _lastGlowPropName;
|
||
|
||
void Awake()
|
||
{
|
||
if (Instance == null) Instance = this;
|
||
else { Destroy(gameObject); return; }
|
||
|
||
if (gameOverPanel) gameOverPanel.SetActive(false);
|
||
|
||
if (!glowMaterial) glowMaterial = playerMaterial;
|
||
_ID_GlowIntensity = Shader.PropertyToID(glowIntensityProp);
|
||
_lastGlowPropName = glowIntensityProp;
|
||
CacheOriginalKeywordStates();
|
||
}
|
||
|
||
void CacheOriginalKeywordStates()
|
||
{
|
||
if (!playerMaterial) return;
|
||
origFade = playerMaterial.IsKeywordEnabled(KW_FADE);
|
||
origGrey = playerMaterial.IsKeywordEnabled(KW_GREYSCALE);
|
||
origGhost = playerMaterial.IsKeywordEnabled(KW_GHOST);
|
||
origOverlay = playerMaterial.IsKeywordEnabled(KW_OVERLAY);
|
||
origOverlayMult = playerMaterial.IsKeywordEnabled(KW_OVERLAYMULT);
|
||
}
|
||
|
||
// --- Public helpers to call from hazards / tests ---
|
||
public void KillBySpikes() => TriggerGameOver(DeathType.Spikes);
|
||
public void KillByLaser() => TriggerGameOver(DeathType.Laser);
|
||
public void KillNormal() => TriggerGameOver(DeathType.Normal);
|
||
|
||
[ContextMenu("TEST: Kill By Spikes")] void _TestKillSpikes() => KillBySpikes();
|
||
[ContextMenu("TEST: Kill By Laser")] void _TestKillLaser() => KillByLaser();
|
||
|
||
public void TriggerGameOver(DeathType type)
|
||
{
|
||
if (isGameOver || player == null) return;
|
||
isGameOver = true;
|
||
|
||
var col = player.GetComponent<Collider>();
|
||
var rb = player.GetComponent<Rigidbody>();
|
||
if (col) col.enabled = false;
|
||
|
||
switch (type)
|
||
{
|
||
case DeathType.Spikes:
|
||
PrepKinematic(rb);
|
||
DeathBySpikes();
|
||
break;
|
||
|
||
case DeathType.Laser:
|
||
PrepKinematic(rb);
|
||
DeathByLaser();
|
||
break;
|
||
|
||
default: // Normal
|
||
player.ForceJumpForGameOver();
|
||
if (rb) { rb.useGravity = true; rb.isKinematic = false; }
|
||
break;
|
||
}
|
||
|
||
GameoverInvoker(); // now 5 seconds
|
||
Debug.Log("GAME OVER!");
|
||
}
|
||
|
||
void PrepKinematic(Rigidbody rb)
|
||
{
|
||
if (!rb) return;
|
||
rb.velocity = Vector3.zero;
|
||
rb.angularVelocity = Vector3.zero;
|
||
rb.useGravity = false;
|
||
rb.isKinematic = true;
|
||
}
|
||
public void PulseBlueberryGlow()
|
||
{
|
||
if (!glowMaterial) return;
|
||
// Refresh property ID if you change the prop name in the Inspector
|
||
if (_lastGlowPropName != glowIntensityProp || _ID_GlowIntensity == 0)
|
||
{
|
||
_ID_GlowIntensity = Shader.PropertyToID(glowIntensityProp);
|
||
_lastGlowPropName = glowIntensityProp;
|
||
}
|
||
|
||
// Kill previous pulse only (don’t touch other tweens like fade)
|
||
if (glowSeq != null && glowSeq.IsActive()) glowSeq.Kill();
|
||
|
||
// Ensure starting at base
|
||
glowMaterial.SetFloat(_ID_GlowIntensity, glowBase);
|
||
|
||
float half = Mathf.Max(0.01f, glowPulseDuration * 0.5f);
|
||
|
||
glowSeq = DOTween.Sequence().SetId("BlueberryGlow")
|
||
.Append(glowMaterial
|
||
.DOFloat(glowPeak, _ID_GlowIntensity, half)
|
||
.SetEase(Ease.OutQuad)
|
||
.SetId("BlueberryGlow"))
|
||
.Append(glowMaterial
|
||
.DOFloat(glowBase, _ID_GlowIntensity, half)
|
||
.SetEase(Ease.InQuad)
|
||
.SetId("BlueberryGlow"));
|
||
|
||
glowSeq.Play();
|
||
}
|
||
|
||
// -------- Death styles --------
|
||
void DeathBySpikes()
|
||
{
|
||
player.animator.Play("Angel");
|
||
BeginHeavenSequence(laserStyle: false);
|
||
}
|
||
|
||
void DeathByLaser()
|
||
{
|
||
player.animator.Play("Angel");
|
||
BeginHeavenSequence(laserStyle: true);
|
||
}
|
||
|
||
public void GameoverInvoker(int duration=5)
|
||
{
|
||
CancelInvoke(nameof(GameoverPanelEnabler));
|
||
Invoke(nameof(GameoverPanelEnabler), duration);
|
||
}
|
||
|
||
public void GameoverPanelEnabler()
|
||
{
|
||
if (gameOverPanel) gameOverPanel.SetActive(true);
|
||
}
|
||
|
||
// -------- Tweens + Shader toggles --------
|
||
void BeginHeavenSequence(bool laserStyle)
|
||
{
|
||
if (deathSeq != null && deathSeq.IsActive()) deathSeq.Kill();
|
||
if (playerMaterial) DOTween.Kill(playerMaterial);
|
||
|
||
// Enable FADE keyword for both styles
|
||
if (playerMaterial)
|
||
{
|
||
playerMaterial.EnableKeyword(KW_FADE);
|
||
|
||
// Style-specific keywords
|
||
if (laserStyle)
|
||
{
|
||
// Laser: Overlay + Ghost, NO Greyscale
|
||
playerMaterial.DisableKeyword(KW_GREYSCALE);
|
||
playerMaterial.EnableKeyword(KW_OVERLAY);
|
||
playerMaterial.DisableKeyword(KW_OVERLAYMULT); // keep overlay in normal blend; enable if you prefer multiply
|
||
playerMaterial.EnableKeyword(KW_GHOST);
|
||
}
|
||
else
|
||
{
|
||
// Spikes: Greyscale + Ghost, NO Overlay
|
||
playerMaterial.EnableKeyword(KW_GREYSCALE);
|
||
playerMaterial.DisableKeyword(KW_OVERLAY);
|
||
playerMaterial.DisableKeyword(KW_OVERLAYMULT);
|
||
playerMaterial.EnableKeyword(KW_GHOST);
|
||
}
|
||
|
||
// Make sure we start visible before fade
|
||
playerMaterial.SetFloat(ID_FadeAmount, -0.1f);
|
||
if (!laserStyle) playerMaterial.SetFloat(ID_FadeBurnWidth, 0f);
|
||
}
|
||
|
||
Vector3 endPos = player.transform.position + Vector3.up * heavenHeight;
|
||
|
||
deathSeq = DOTween.Sequence();
|
||
|
||
if (laserStyle && playerMaterial)
|
||
{
|
||
// Laser: widen burn first
|
||
deathSeq.Append(playerMaterial.DOFloat(1f, ID_FadeBurnWidth, 0.5f));
|
||
}
|
||
|
||
// Float up like an angel
|
||
deathSeq.Append(player.transform.DOMoveY(endPos.y, ascendDuration).SetEase(Ease.OutSine));
|
||
// Wait before final fade
|
||
deathSeq.AppendInterval(fadeDelay);
|
||
|
||
// Final fade to 1
|
||
if (playerMaterial)
|
||
deathSeq.Append(playerMaterial.DOFloat(1f, ID_FadeAmount, fadeDuration));
|
||
|
||
deathSeq.Play();
|
||
}
|
||
|
||
// -------- Revert shader changes on disable --------
|
||
void OnDisable()
|
||
{
|
||
if (deathSeq != null && deathSeq.IsActive()) deathSeq.Kill();
|
||
DOTween.Kill(playerMaterial);
|
||
|
||
if (playerMaterial)
|
||
{
|
||
// revert fade values
|
||
playerMaterial.SetFloat(ID_FadeAmount, 0f);
|
||
playerMaterial.SetFloat(ID_FadeBurnWidth, 0f);
|
||
|
||
// restore original keywords
|
||
SetKeyword(playerMaterial, KW_FADE, origFade);
|
||
SetKeyword(playerMaterial, KW_GREYSCALE, origGrey);
|
||
SetKeyword(playerMaterial, KW_GHOST, origGhost);
|
||
SetKeyword(playerMaterial, KW_OVERLAY, origOverlay);
|
||
SetKeyword(playerMaterial, KW_OVERLAYMULT, origOverlayMult);
|
||
}
|
||
|
||
if (glowSeq != null && glowSeq.IsActive()) glowSeq.Kill();
|
||
DOTween.Kill("BlueberryGlow");
|
||
if (glowMaterial) glowMaterial.SetFloat(_ID_GlowIntensity, glowBase);
|
||
|
||
}
|
||
|
||
static void SetKeyword(Material m, string keyword, bool enabled)
|
||
{
|
||
if (!m) return;
|
||
if (enabled) m.EnableKeyword(keyword);
|
||
else m.DisableKeyword(keyword);
|
||
}
|
||
}
|