mirror of
https://github.com/Earth-Genesis-Games/Carrasco.git
synced 2026-09-11 09:52:19 +00:00
menues fix
This commit is contained in:
+220
-44
@@ -1,70 +1,246 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Pausa segura para overlays/menús (tutorial incluido).
|
||||
/// - Si existe GameManager, marca isPaused = true y deja que él ponga timeScale=0.
|
||||
/// - Si no existe GameManager, hace fallback a pausar con Time.timeScale = 0.
|
||||
/// - Al desactivar el GO, restaura el estado.
|
||||
/// Recomendado: que el Canvas tenga un Graphic (Image) con raycastTarget=true para bloquear clicks a la escena.
|
||||
/// 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
|
||||
{
|
||||
private bool _weChangedPause = false;
|
||||
private float _prevTimeScale = 1f;
|
||||
private bool _prevAudioPause = false;
|
||||
// -------- 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()
|
||||
{
|
||||
// Si hay GameManager, usamos su flag isPaused (él se encarga del timeScale en Update).
|
||||
var gm = GameManager.Instance;
|
||||
if (gm != null)
|
||||
{
|
||||
// Evita interferir si el juego está en game over o win.
|
||||
if (!gm.isPausedByGameOver && !gm.IsWin())
|
||||
{
|
||||
gm.isPaused = true; // GameManager.Update pondrá Time.timeScale = 0f
|
||||
_weChangedPause = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// En estados especiales, no tocamos flags del GM. Igual bloqueamos el audio.
|
||||
_prevAudioPause = AudioListener.pause;
|
||||
AudioListener.pause = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback si no hay GameManager en escena.
|
||||
_prevTimeScale = Time.timeScale;
|
||||
_prevAudioPause = AudioListener.pause;
|
||||
s_activeTokens++;
|
||||
_weHoldToken = true;
|
||||
|
||||
Time.timeScale = 0f;
|
||||
AudioListener.pause = true;
|
||||
_weChangedPause = 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 (_weChangedPause && gm.isPaused && !gm.isPausedByGameOver && !gm.IsWin())
|
||||
gm.isPaused = false; // GameManager.Update restaurará timeScale=1
|
||||
|
||||
// Siempre devolvemos el audio a su estado previo si lo tocamos
|
||||
AudioListener.pause = _prevAudioPause;
|
||||
if (gm.isPausedByGameOver || gm.IsWin() || gm.isPaused)
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
Time.timeScale = 1f;
|
||||
}
|
||||
|
||||
// =========================================================
|
||||
// Spawners: snapshot + disable + restore
|
||||
// =========================================================
|
||||
private void DisableAllSpawners()
|
||||
{
|
||||
s_spawnerSnapshots.Clear();
|
||||
|
||||
var allBehaviours = FindObjectsOfType<MonoBehaviour>(true);
|
||||
foreach (var mb in allBehaviours)
|
||||
{
|
||||
if (_weChangedPause)
|
||||
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"))
|
||||
{
|
||||
Time.timeScale = (_prevTimeScale <= 0f) ? 1f : _prevTimeScale;
|
||||
AudioListener.pause = _prevAudioPause;
|
||||
SnapshotAndDisable(mb);
|
||||
}
|
||||
}
|
||||
|
||||
_weChangedPause = false;
|
||||
#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;
|
||||
}
|
||||
}
|
||||
@@ -2439,10 +2439,10 @@ RectTransform:
|
||||
m_Children: []
|
||||
m_Father: {fileID: 800283092}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 8.262}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: -211, y: 27}
|
||||
m_SizeDelta: {x: 628.3042, y: 235.614}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: -211, y: 60.74022}
|
||||
m_SizeDelta: {x: -651.6958, y: -844.386}
|
||||
m_Pivot: {x: 0.5, y: 0.46875906}
|
||||
--- !u!114 &601115176
|
||||
MonoBehaviour:
|
||||
@@ -7464,9 +7464,6 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: d4032d7acb4a649fb9806dd8c433325d, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
requestEmail: 0
|
||||
requestIdToken: 1
|
||||
requestServerAuthCode: 1
|
||||
--- !u!4 &1770338342
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
Reference in New Issue
Block a user