2025-09-01 00:01:33 +05:00
|
|
|
|
using UnityEngine;
|
2025-09-06 23:30:06 +05:00
|
|
|
|
using DG.Tweening;
|
|
|
|
|
|
|
|
|
|
public enum DeathType { Normal, Laser, Spikes }
|
2025-09-01 00:01:33 +05:00
|
|
|
|
|
|
|
|
|
public class Skywalker_GameManager : MonoBehaviour
|
|
|
|
|
{
|
2025-09-06 23:30:06 +05:00
|
|
|
|
public static Skywalker_GameManager Instance;
|
2025-09-01 00:01:33 +05:00
|
|
|
|
|
|
|
|
|
[Header("UI References")]
|
|
|
|
|
public GameObject gameOverPanel;
|
|
|
|
|
|
|
|
|
|
[Header("Player Reference")]
|
|
|
|
|
public Skywalker_PlayerController player; // assign in inspector
|
|
|
|
|
|
2025-09-06 23:30:06 +05:00
|
|
|
|
[Header("Heaven Tween")]
|
|
|
|
|
public float heavenHeight = 4f; // ascent height
|
2025-09-07 02:00:26 +05:00
|
|
|
|
public float ascendDuration = 2.5f; // ascent time
|
|
|
|
|
public float fadeDelay = 2.0f; // wait before fade (2<>3s)
|
2025-09-06 23:30:06 +05:00
|
|
|
|
public float fadeDuration = 0.5f; // fade to 1
|
|
|
|
|
|
|
|
|
|
[Header("Material (AllIn1SpriteShader)")]
|
|
|
|
|
public Material playerMaterial;
|
|
|
|
|
|
2025-09-01 00:01:33 +05:00
|
|
|
|
private bool isGameOver = false;
|
|
|
|
|
|
2025-09-06 23:30:06 +05:00
|
|
|
|
// AllIn1SpriteShader property IDs
|
|
|
|
|
static readonly int ID_FadeAmount = Shader.PropertyToID("_FadeAmount");
|
|
|
|
|
static readonly int ID_FadeBurnWidth = Shader.PropertyToID("_FadeBurnWidth");
|
2025-09-07 02:00:26 +05:00
|
|
|
|
static readonly int ID_GreyscaleBlend = Shader.PropertyToID("_GreyscaleBlend"); // <-- added
|
|
|
|
|
static readonly int ID_GhostBlend = Shader.PropertyToID("_GhostBlend"); // <-- added
|
2025-09-06 23:30:06 +05:00
|
|
|
|
|
2025-09-07 02:00:26 +05:00
|
|
|
|
// AllIn1SpriteShader keywords (kept; safe even if features are enabled on the asset)
|
2025-09-06 23:30:06 +05:00
|
|
|
|
const string KW_FADE = "FADE_ON";
|
|
|
|
|
const string KW_GREYSCALE = "GREYSCALE_ON";
|
|
|
|
|
const string KW_GHOST = "GHOST_ON";
|
|
|
|
|
const string KW_OVERLAY = "OVERLAY_ON";
|
2025-09-07 02:00:26 +05:00
|
|
|
|
const string KW_OVERLAYMULT = "OVERLAYMULT_ON";
|
2025-09-06 23:30:06 +05:00
|
|
|
|
|
|
|
|
|
// store original keyword states so we can restore on disable
|
|
|
|
|
bool origFade, origGrey, origGhost, origOverlay, origOverlayMult;
|
|
|
|
|
|
|
|
|
|
Sequence deathSeq;
|
2025-09-07 02:00:26 +05:00
|
|
|
|
|
2025-09-06 23:30:06 +05:00
|
|
|
|
// --- 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).")]
|
2025-09-07 02:00:26 +05:00
|
|
|
|
public string glowIntensityProp = "_Glow"; // <-- default corrected to _Glow
|
2025-09-06 23:30:06 +05:00
|
|
|
|
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;
|
2025-09-07 02:00:26 +05:00
|
|
|
|
static readonly int ID_OverlayBlend = Shader.PropertyToID("_OverlayBlend");
|
2025-09-06 23:30:06 +05:00
|
|
|
|
|
2025-09-01 00:01:33 +05:00
|
|
|
|
void Awake()
|
|
|
|
|
{
|
|
|
|
|
if (Instance == null) Instance = this;
|
2025-09-06 23:30:06 +05:00
|
|
|
|
else { Destroy(gameObject); return; }
|
|
|
|
|
|
|
|
|
|
if (gameOverPanel) gameOverPanel.SetActive(false);
|
2025-09-01 00:01:33 +05:00
|
|
|
|
|
2025-09-06 23:30:06 +05:00
|
|
|
|
if (!glowMaterial) glowMaterial = playerMaterial;
|
|
|
|
|
_ID_GlowIntensity = Shader.PropertyToID(glowIntensityProp);
|
|
|
|
|
_lastGlowPropName = glowIntensityProp;
|
2025-09-07 02:00:26 +05:00
|
|
|
|
|
2025-09-06 23:30:06 +05:00
|
|
|
|
CacheOriginalKeywordStates();
|
2025-09-01 00:01:33 +05:00
|
|
|
|
}
|
|
|
|
|
|
2025-09-06 23:30:06 +05:00
|
|
|
|
void CacheOriginalKeywordStates()
|
2025-09-01 00:01:33 +05:00
|
|
|
|
{
|
2025-09-06 23:30:06 +05:00
|
|
|
|
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;
|
2025-09-01 00:01:33 +05:00
|
|
|
|
isGameOver = true;
|
|
|
|
|
|
2025-09-06 23:30:06 +05:00
|
|
|
|
var col = player.GetComponent<Collider>();
|
|
|
|
|
var rb = player.GetComponent<Rigidbody>();
|
|
|
|
|
if (col) col.enabled = false;
|
|
|
|
|
|
|
|
|
|
switch (type)
|
2025-09-01 00:01:33 +05:00
|
|
|
|
{
|
2025-09-06 23:30:06 +05:00
|
|
|
|
case DeathType.Spikes:
|
|
|
|
|
PrepKinematic(rb);
|
|
|
|
|
DeathBySpikes();
|
|
|
|
|
break;
|
2025-09-01 00:01:33 +05:00
|
|
|
|
|
2025-09-06 23:30:06 +05:00
|
|
|
|
case DeathType.Laser:
|
|
|
|
|
PrepKinematic(rb);
|
|
|
|
|
DeathByLaser();
|
|
|
|
|
break;
|
2025-09-01 00:01:33 +05:00
|
|
|
|
|
2025-09-06 23:30:06 +05:00
|
|
|
|
default: // Normal
|
|
|
|
|
player.ForceJumpForGameOver();
|
|
|
|
|
if (rb) { rb.useGravity = true; rb.isKinematic = false; }
|
|
|
|
|
break;
|
2025-09-01 00:01:33 +05:00
|
|
|
|
}
|
|
|
|
|
|
2025-09-06 23:30:06 +05:00
|
|
|
|
GameoverInvoker(); // now 5 seconds
|
2025-09-01 00:01:33 +05:00
|
|
|
|
Debug.Log("GAME OVER!");
|
|
|
|
|
}
|
2025-09-06 23:30:06 +05:00
|
|
|
|
|
|
|
|
|
void PrepKinematic(Rigidbody rb)
|
2025-09-01 00:01:33 +05:00
|
|
|
|
{
|
2025-09-06 23:30:06 +05:00
|
|
|
|
if (!rb) return;
|
|
|
|
|
rb.velocity = Vector3.zero;
|
|
|
|
|
rb.angularVelocity = Vector3.zero;
|
|
|
|
|
rb.useGravity = false;
|
|
|
|
|
rb.isKinematic = true;
|
2025-09-01 00:01:33 +05:00
|
|
|
|
}
|
2025-09-07 02:00:26 +05:00
|
|
|
|
|
2025-09-06 23:30:06 +05:00
|
|
|
|
public void PulseBlueberryGlow()
|
|
|
|
|
{
|
|
|
|
|
if (!glowMaterial) return;
|
2025-09-07 02:00:26 +05:00
|
|
|
|
|
2025-09-06 23:30:06 +05:00
|
|
|
|
// 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<6F>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")
|
2025-09-07 02:00:26 +05:00
|
|
|
|
.Append(glowMaterial.DOFloat(glowPeak, _ID_GlowIntensity, half).SetEase(Ease.OutQuad).SetId("BlueberryGlow"))
|
|
|
|
|
.Append(glowMaterial.DOFloat(glowBase, _ID_GlowIntensity, half).SetEase(Ease.InQuad).SetId("BlueberryGlow"));
|
2025-09-06 23:30:06 +05:00
|
|
|
|
|
|
|
|
|
glowSeq.Play();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------- Death styles --------
|
|
|
|
|
void DeathBySpikes()
|
|
|
|
|
{
|
|
|
|
|
player.animator.Play("Angel");
|
|
|
|
|
BeginHeavenSequence(laserStyle: false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DeathByLaser()
|
|
|
|
|
{
|
|
|
|
|
player.animator.Play("Angel");
|
|
|
|
|
BeginHeavenSequence(laserStyle: true);
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-07 02:00:26 +05:00
|
|
|
|
public void GameoverInvoker(int duration = 5)
|
2025-09-06 23:30:06 +05:00
|
|
|
|
{
|
|
|
|
|
CancelInvoke(nameof(GameoverPanelEnabler));
|
|
|
|
|
Invoke(nameof(GameoverPanelEnabler), duration);
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-01 00:01:33 +05:00
|
|
|
|
public void GameoverPanelEnabler()
|
|
|
|
|
{
|
2025-09-06 23:30:06 +05:00
|
|
|
|
if (gameOverPanel) gameOverPanel.SetActive(true);
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-07 02:00:26 +05:00
|
|
|
|
// -------- Tweens + Shader toggles / values --------
|
2025-09-06 23:30:06 +05:00
|
|
|
|
void BeginHeavenSequence(bool laserStyle)
|
|
|
|
|
{
|
|
|
|
|
if (deathSeq != null && deathSeq.IsActive()) deathSeq.Kill();
|
|
|
|
|
if (playerMaterial) DOTween.Kill(playerMaterial);
|
|
|
|
|
|
|
|
|
|
if (playerMaterial)
|
|
|
|
|
{
|
|
|
|
|
playerMaterial.EnableKeyword(KW_FADE);
|
|
|
|
|
|
|
|
|
|
if (laserStyle)
|
|
|
|
|
{
|
|
|
|
|
// Laser: Overlay + Ghost, NO Greyscale
|
|
|
|
|
playerMaterial.DisableKeyword(KW_GREYSCALE);
|
|
|
|
|
playerMaterial.EnableKeyword(KW_OVERLAY);
|
2025-09-07 02:00:26 +05:00
|
|
|
|
playerMaterial.DisableKeyword(KW_OVERLAYMULT);
|
2025-09-06 23:30:06 +05:00
|
|
|
|
playerMaterial.EnableKeyword(KW_GHOST);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2025-09-07 02:00:26 +05:00
|
|
|
|
// Spikes: Greyscale + Ghost, NO Overlay (+ make sure OVERLAYMULT is OFF)
|
2025-09-06 23:30:06 +05:00
|
|
|
|
playerMaterial.EnableKeyword(KW_GREYSCALE);
|
|
|
|
|
playerMaterial.DisableKeyword(KW_OVERLAY);
|
|
|
|
|
playerMaterial.DisableKeyword(KW_OVERLAYMULT);
|
|
|
|
|
playerMaterial.EnableKeyword(KW_GHOST);
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-07 02:00:26 +05:00
|
|
|
|
// Ensure visible before fade
|
2025-09-06 23:30:06 +05:00
|
|
|
|
playerMaterial.SetFloat(ID_FadeAmount, -0.1f);
|
|
|
|
|
if (!laserStyle) playerMaterial.SetFloat(ID_FadeBurnWidth, 0f);
|
2025-09-07 02:00:26 +05:00
|
|
|
|
|
|
|
|
|
// Start blends from zero so tweens are visible
|
|
|
|
|
playerMaterial.SetFloat(ID_GreyscaleBlend, 0f);
|
|
|
|
|
playerMaterial.SetFloat(ID_GhostBlend, 0f);
|
|
|
|
|
playerMaterial.SetFloat(ID_OverlayBlend, 0f);
|
2025-09-06 23:30:06 +05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Vector3 endPos = player.transform.position + Vector3.up * heavenHeight;
|
|
|
|
|
|
|
|
|
|
deathSeq = DOTween.Sequence();
|
|
|
|
|
|
|
|
|
|
if (laserStyle && playerMaterial)
|
|
|
|
|
{
|
2025-09-07 02:00:26 +05:00
|
|
|
|
// Start ALL laser visuals together:
|
|
|
|
|
// - BurnWidth widens (0.5s)
|
|
|
|
|
// - Ghost 0 -> 0.65 (0.35s)
|
|
|
|
|
// - Overlay 0 -> 1.0 (0.35s)
|
|
|
|
|
deathSeq.Append(playerMaterial.DOFloat(1f, ID_FadeBurnWidth, 0.5f)); // append first
|
|
|
|
|
deathSeq.Join(playerMaterial.DOFloat(0.65f, ID_GhostBlend, 0.35f).SetEase(Ease.OutQuad));
|
|
|
|
|
deathSeq.Join(playerMaterial.DOFloat(1.0f, ID_OverlayBlend, 0.35f).SetEase(Ease.OutQuad));
|
|
|
|
|
}
|
|
|
|
|
else if (playerMaterial)
|
|
|
|
|
{
|
|
|
|
|
// Spikes: Greyscale 0 -> 0.7, Ghost 0 -> 0.65 together
|
|
|
|
|
deathSeq.Join(playerMaterial.DOFloat(0.7f, ID_GreyscaleBlend, 0.35f).SetEase(Ease.OutQuad));
|
|
|
|
|
deathSeq.Join(playerMaterial.DOFloat(0.65f, ID_GhostBlend, 0.35f).SetEase(Ease.OutQuad));
|
2025-09-06 23:30:06 +05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Float up like an angel
|
|
|
|
|
deathSeq.Append(player.transform.DOMoveY(endPos.y, ascendDuration).SetEase(Ease.OutSine));
|
2025-09-07 02:00:26 +05:00
|
|
|
|
|
2025-09-06 23:30:06 +05:00
|
|
|
|
// Wait before final fade
|
|
|
|
|
deathSeq.AppendInterval(fadeDelay);
|
|
|
|
|
|
|
|
|
|
// Final fade to 1
|
|
|
|
|
if (playerMaterial)
|
2025-09-07 02:00:26 +05:00
|
|
|
|
{
|
|
|
|
|
if (laserStyle)
|
|
|
|
|
{
|
|
|
|
|
// Laser: fade out AND shrink burn width back to 0 at the same time
|
|
|
|
|
deathSeq.Append(playerMaterial.DOFloat(1f, ID_FadeAmount, fadeDuration));
|
|
|
|
|
deathSeq.Join(playerMaterial.DOFloat(0f, ID_FadeBurnWidth, fadeDuration)); // <- new
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Spikes: just fade out
|
|
|
|
|
deathSeq.Append(playerMaterial.DOFloat(1f, ID_FadeAmount, fadeDuration));
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-09-06 23:30:06 +05:00
|
|
|
|
deathSeq.Play();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------- Revert shader changes on disable --------
|
|
|
|
|
void OnDisable()
|
|
|
|
|
{
|
|
|
|
|
if (deathSeq != null && deathSeq.IsActive()) deathSeq.Kill();
|
|
|
|
|
DOTween.Kill(playerMaterial);
|
2025-09-07 02:00:26 +05:00
|
|
|
|
playerMaterial.SetFloat(ID_OverlayBlend, 0f);
|
2025-09-06 23:30:06 +05:00
|
|
|
|
if (playerMaterial)
|
|
|
|
|
{
|
|
|
|
|
// revert fade values
|
|
|
|
|
playerMaterial.SetFloat(ID_FadeAmount, 0f);
|
|
|
|
|
playerMaterial.SetFloat(ID_FadeBurnWidth, 0f);
|
2025-09-07 02:00:26 +05:00
|
|
|
|
// revert blends
|
|
|
|
|
playerMaterial.SetFloat(ID_GreyscaleBlend, 0f);
|
|
|
|
|
playerMaterial.SetFloat(ID_GhostBlend, 0f);
|
2025-09-06 23:30:06 +05:00
|
|
|
|
|
|
|
|
|
// 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);
|
2025-09-01 00:01:33 +05:00
|
|
|
|
}
|
|
|
|
|
}
|