mirror of
https://github.com/Earth-Genesis-Games/Carrasco.git
synced 2026-09-11 09:52:19 +00:00
246 lines
7.9 KiB
C#
246 lines
7.9 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
/// <summary>
|
|
/// Pausa robusta para overlays/menús (tutorial, modales, etc).
|
|
/// - timeScale = 0 mientras haya overlays activos (ref-count).
|
|
/// - Desactiva todos los spawners (DynamicSpawnerSystem, *Spawner*, etc) y luego los restaura.
|
|
/// - Anti-backlog + anti-parpadeo: cualquier avión instanciado durante la pausa se
|
|
/// deshabilita visualmente en el mismo frame y luego se destruye.
|
|
/// </summary>
|
|
[DisallowMultipleComponent]
|
|
[DefaultExecutionOrder(10000)]
|
|
public class PauseForMenuesChotos : MonoBehaviour
|
|
{
|
|
// -------- estado global (entre múltiples overlays) --------
|
|
private static int s_activeTokens = 0;
|
|
|
|
private struct SpawnerSnapshot
|
|
{
|
|
public Behaviour behaviour;
|
|
public bool wasEnabled;
|
|
public GameObject go;
|
|
public bool goWasActive;
|
|
}
|
|
|
|
private static readonly List<SpawnerSnapshot> s_spawnerSnapshots = new List<SpawnerSnapshot>();
|
|
private static bool s_spawnersDisabled = false;
|
|
|
|
// Conjunto de aviones que ya existían al entrar en pausa (no se tocan)
|
|
private static readonly HashSet<int> s_knownPlaneIds = new HashSet<int>();
|
|
|
|
// Único dueño de la patrulla anti-parpadeo
|
|
private static PauseForMenuesChotos s_cullOwner = null;
|
|
private Coroutine _cullCo;
|
|
|
|
// -------- por-instancia --------
|
|
private bool _weHoldToken = false;
|
|
private bool _prevAudioPause = false;
|
|
|
|
private void OnEnable()
|
|
{
|
|
s_activeTokens++;
|
|
_weHoldToken = true;
|
|
|
|
_prevAudioPause = AudioListener.pause;
|
|
AudioListener.pause = true;
|
|
|
|
ForceTimeScaleZero();
|
|
|
|
var gm = GameManager.Instance;
|
|
if (gm != null && !gm.isPausedByGameOver && !gm.IsWin())
|
|
gm.isPaused = true;
|
|
|
|
// Primer overlay que entra → apagar spawners y capturar baseline de aviones
|
|
if (!s_spawnersDisabled)
|
|
{
|
|
DisableAllSpawners();
|
|
s_spawnersDisabled = true;
|
|
|
|
// Baseline: registrar aviones existentes
|
|
s_knownPlaneIds.Clear();
|
|
var planesNow = FindObjectsOfType<PlaneController>(true);
|
|
for (int i = 0; i < planesNow.Length; i++)
|
|
if (planesNow[i]) s_knownPlaneIds.Add(planesNow[i].GetInstanceID());
|
|
}
|
|
|
|
// Arrancar patrulla por frame sólo si no hay otra en curso
|
|
if (s_cullOwner == null)
|
|
{
|
|
s_cullOwner = this;
|
|
_cullCo = StartCoroutine(CoCullNewSpawnsEveryFrame());
|
|
}
|
|
}
|
|
|
|
private void LateUpdate()
|
|
{
|
|
if (s_activeTokens > 0)
|
|
ForceTimeScaleZero(); // por si alguien tocó el timeScale
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
if (_weHoldToken)
|
|
{
|
|
s_activeTokens = Mathf.Max(0, s_activeTokens - 1);
|
|
_weHoldToken = false;
|
|
}
|
|
|
|
AudioListener.pause = _prevAudioPause;
|
|
|
|
// Si aún quedan overlays activos, no restauramos
|
|
if (s_activeTokens > 0) return;
|
|
|
|
// Detener patrulla si éramos dueños
|
|
if (s_cullOwner == this)
|
|
{
|
|
if (_cullCo != null) StopCoroutine(_cullCo);
|
|
_cullCo = null;
|
|
s_cullOwner = null;
|
|
}
|
|
|
|
// Restaurar spawners
|
|
if (s_spawnersDisabled)
|
|
{
|
|
RestoreAllSpawners();
|
|
s_spawnersDisabled = false;
|
|
}
|
|
|
|
s_knownPlaneIds.Clear();
|
|
|
|
var gm = GameManager.Instance;
|
|
if (gm != null)
|
|
{
|
|
if (gm.isPausedByGameOver || gm.IsWin() || gm.isPaused)
|
|
return;
|
|
}
|
|
|
|
Time.timeScale = 1f;
|
|
}
|
|
|
|
// =========================================================
|
|
// Spawners: snapshot + disable + restore
|
|
// =========================================================
|
|
private void DisableAllSpawners()
|
|
{
|
|
s_spawnerSnapshots.Clear();
|
|
|
|
var allBehaviours = FindObjectsOfType<MonoBehaviour>(true);
|
|
foreach (var mb in allBehaviours)
|
|
{
|
|
if (!mb) continue;
|
|
var tn = mb.GetType().Name;
|
|
|
|
// Todo lo que suene a "Spawner" o el sistema dinámico explícito
|
|
if (tn == "DynamicSpawnerSystem" || tn.Contains("Spawner") || tn.Contains("Spawn"))
|
|
{
|
|
SnapshotAndDisable(mb);
|
|
}
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
Debug.Log($"[PauseForMenuesChotos] Spawners desactivados: {s_spawnerSnapshots.Count} componentes.");
|
|
#endif
|
|
}
|
|
|
|
private void SnapshotAndDisable(MonoBehaviour mb)
|
|
{
|
|
var go = mb.gameObject;
|
|
s_spawnerSnapshots.Add(new SpawnerSnapshot
|
|
{
|
|
behaviour = mb,
|
|
wasEnabled = mb.enabled,
|
|
go = go,
|
|
goWasActive = go.activeSelf
|
|
});
|
|
|
|
// Desactivar GO (corta Updates/Coroutines/Invoke) y además el enabled
|
|
if (go.activeSelf) go.SetActive(false);
|
|
if (mb.enabled) mb.enabled = false;
|
|
}
|
|
|
|
private void RestoreAllSpawners()
|
|
{
|
|
for (int i = 0; i < s_spawnerSnapshots.Count; i++)
|
|
{
|
|
var s = s_spawnerSnapshots[i];
|
|
if (!s.behaviour) continue;
|
|
|
|
if (s.go) s.go.SetActive(s.goWasActive);
|
|
s.behaviour.enabled = s.wasEnabled;
|
|
}
|
|
s_spawnerSnapshots.Clear();
|
|
|
|
#if UNITY_EDITOR
|
|
Debug.Log("[PauseForMenuesChotos] Spawners restaurados.");
|
|
#endif
|
|
}
|
|
|
|
// =========================================================
|
|
// Anti-parpadeo: patrulla *cada frame* y apaga renderers antes de destruir
|
|
// =========================================================
|
|
private IEnumerator CoCullNewSpawnsEveryFrame()
|
|
{
|
|
// Primera pasada inmediata (mismo frame) sin esperar
|
|
while (s_activeTokens > 0)
|
|
{
|
|
ForceTimeScaleZero();
|
|
|
|
var planes = FindObjectsOfType<PlaneController>(true);
|
|
for (int i = 0; i < planes.Length; i++)
|
|
{
|
|
var p = planes[i];
|
|
if (!p) continue;
|
|
|
|
int id = p.GetInstanceID();
|
|
if (s_knownPlaneIds.Contains(id)) continue; // ya existía antes de pausar
|
|
|
|
// ---- NUEVO DURANTE PAUSA → ocultar y destruir ----
|
|
// Apagar renderers/colliders YA (evita que se dibuje ni 1 frame)
|
|
try
|
|
{
|
|
var rends = p.GetComponentsInChildren<Renderer>(true);
|
|
for (int r = 0; r < rends.Length; r++) if (rends[r]) rends[r].enabled = false;
|
|
|
|
var cols = p.GetComponentsInChildren<Collider2D>(true);
|
|
for (int c = 0; c < cols.Length; c++) if (cols[c]) cols[c].enabled = false;
|
|
|
|
var rb = p.GetComponent<Rigidbody2D>();
|
|
if (rb) { rb.simulated = false; rb.linearVelocity = Vector2.zero; rb.angularVelocity = 0f; }
|
|
|
|
// Opcional: ocultar también cualquier LineRenderer/Trail
|
|
var lrs = p.GetComponentsInChildren<LineRenderer>(true);
|
|
for (int l = 0; l < lrs.Length; l++) if (lrs[l]) lrs[l].enabled = false;
|
|
|
|
var trs = p.GetComponentsInChildren<TrailRenderer>(true);
|
|
for (int t = 0; t < trs.Length; t++) if (trs[t]) trs[t].emitting = false;
|
|
}
|
|
catch { /* seguro */ }
|
|
|
|
#if UNITY_EDITOR
|
|
Debug.Log($"[PauseForMenuesChotos] Cull avión nuevo durante pausa: {p.name}");
|
|
#endif
|
|
|
|
#if UNITY_EDITOR
|
|
if (!Application.isPlaying) DestroyImmediate(p.gameObject);
|
|
else
|
|
#endif
|
|
Destroy(p.gameObject);
|
|
|
|
// No lo agregamos al baseline (ya está marcado para destruir)
|
|
}
|
|
|
|
// Esperamos al siguiente frame (realtime) para seguir patrullando
|
|
yield return null; // cada frame
|
|
}
|
|
}
|
|
|
|
// =========================================================
|
|
// Utilidades
|
|
// =========================================================
|
|
private static void ForceTimeScaleZero()
|
|
{
|
|
if (Time.timeScale != 0f) Time.timeScale = 0f;
|
|
}
|
|
} |