超大量的更新 修复很多问题,gameplay特效初步
This commit is contained in:
@@ -1,43 +1,88 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Simple pause manager. Call Pause(true) to pause or Pause(false) to resume.
|
||||
/// - overlayRoot: GameObject that will be enabled when paused and disabled when resumed.
|
||||
/// - Pressing Escape toggles pause while the manager exists.
|
||||
/// Central gameplay pause manager.
|
||||
/// - ESC / top-right Pause button can pause only in gameplay scene.
|
||||
/// - Continue: hide pause panel, replay 3-2-1-Go, then resume chart + music.
|
||||
/// - Replay: reload current gameplay scene (with current selected song/difficulty if available).
|
||||
/// - Exit: return to selectYourSongFirst.
|
||||
/// </summary>
|
||||
public class PauseManager : MonoBehaviour
|
||||
{
|
||||
public static PauseManager Instance { get; private set; }
|
||||
|
||||
[Header("Overlay")]
|
||||
public GameObject overlayRoot; // object to enable/disable on pause
|
||||
public GameObject overlayRoot;
|
||||
[SerializeField] private float overlayFadeDuration = 0.2f;
|
||||
[SerializeField] private bool preferPausePrefabOverWhiteScreen = true;
|
||||
[SerializeField] private string legacyWhiteScreenRootName = "pauseWhiteScreen";
|
||||
|
||||
[Header("Gameplay Scope")]
|
||||
[SerializeField] private bool onlyInGameplayScene = true;
|
||||
[SerializeField] private string gameplaySceneName = "gamePlay_gamePlay";
|
||||
[SerializeField] private bool requirePlaybackStarted = true;
|
||||
|
||||
[Header("Buttons")]
|
||||
[SerializeField] private string pauseButtonScenePath = "artworks/NEW UI/zhuangshi (3)/Pause";
|
||||
[SerializeField] private Button pauseTriggerButton;
|
||||
[SerializeField] private Button continueButton;
|
||||
[SerializeField] private Button replayButton;
|
||||
[SerializeField] private Button exitButton;
|
||||
[SerializeField] private Button settingsButton;
|
||||
|
||||
[Header("Pause Entry Animation")]
|
||||
[SerializeField] private bool playPauseEntryAnimation = true;
|
||||
[SerializeField] private float pauseItemEnterDuration = 0.18f;
|
||||
[SerializeField] private float pauseItemEnterStagger = 0.016f;
|
||||
|
||||
public bool IsPaused { get; private set; } = false;
|
||||
|
||||
// ������ͣ״̬�ı��¼�
|
||||
public event Action<bool> OnPauseStateChanged;
|
||||
|
||||
private CanvasGroup overlayCanvasGroup;
|
||||
private RectTransform overlayPanelRoot;
|
||||
private CanvasGroup overlayPanelCanvasGroup;
|
||||
private Vector3 panelShownScale = Vector3.zero;
|
||||
private static readonly Vector3 PanelHiddenScale = Vector3.zero;
|
||||
private Coroutine overlayFadeCoroutine;
|
||||
private Coroutine continueCoroutine;
|
||||
private bool buttonsBound = false;
|
||||
private float nextBindRetryTime = 0f;
|
||||
|
||||
private const string ExitSceneName = "selectYourSongFirst";
|
||||
|
||||
void Awake()
|
||||
{
|
||||
if (Instance == null) Instance = this;
|
||||
else Destroy(gameObject);
|
||||
else
|
||||
{
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
if (overlayRoot != null)
|
||||
overlayRoot.SetActive(false);
|
||||
ResolveOverlayRootForPausePrefab();
|
||||
EnsureOverlayCanvasGroup();
|
||||
EnsureOverlayPanelRoot();
|
||||
SetOverlayVisibleImmediate(false);
|
||||
TryBindButtons(force: true);
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
// Delete = immediate quit (stop play in editor or quit app)
|
||||
if (!buttonsBound && Time.unscaledTime >= nextBindRetryTime)
|
||||
{
|
||||
TryBindButtons(force: false);
|
||||
}
|
||||
|
||||
if (Input.GetKeyDown(KeyCode.Delete))
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
@@ -50,54 +95,599 @@ public class PauseManager : MonoBehaviour
|
||||
|
||||
if (Input.GetKeyDown(KeyCode.Escape))
|
||||
{
|
||||
TogglePause();
|
||||
// User requested ESC as pause trigger in gameplay only.
|
||||
if (CanPauseFromInput() && !IsPaused)
|
||||
{
|
||||
Pause(true);
|
||||
}
|
||||
}
|
||||
|
||||
// ��������ͣ״̬�Ұ��� Backspace ʱ����������
|
||||
// Keep existing Backspace quick-exit while paused.
|
||||
if (IsPaused && Input.GetKeyDown(KeyCode.Backspace))
|
||||
{
|
||||
// �ָ�ʱ�����������¼���Ȼ�����������
|
||||
Pause(false);
|
||||
// ȷ��������������Ŀ�е�������ƥ��
|
||||
StartCoroutine(LoadSceneAsync("Main_main"));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pause or resume the game. Call Pause(true) to pause.
|
||||
/// This implementation enables/disables overlayRoot and sets Time.timeScale.
|
||||
/// </summary>
|
||||
public void Pause(bool pause)
|
||||
{
|
||||
if (pause)
|
||||
{
|
||||
if (IsPaused) return;
|
||||
if (overlayRoot != null) overlayRoot.SetActive(true);
|
||||
Time.timeScale = 0f;
|
||||
IsPaused = true;
|
||||
Time.timeScale = 0f;
|
||||
OnPauseStateChanged?.Invoke(true);
|
||||
// Startup flows call Pause(true) before real gameplay starts.
|
||||
// In that phase we keep time paused but do not show pause UI.
|
||||
bool allowOverlay = CanPauseFromInput();
|
||||
if (allowOverlay)
|
||||
ShowOverlayAnimated(true);
|
||||
else
|
||||
SetOverlayVisibleImmediate(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!IsPaused) return;
|
||||
if (overlayRoot != null) overlayRoot.SetActive(false);
|
||||
Time.timeScale = 1f;
|
||||
IsPaused = false;
|
||||
Time.timeScale = 1f;
|
||||
OnPauseStateChanged?.Invoke(false);
|
||||
ShowOverlayAnimated(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void TogglePause()
|
||||
{
|
||||
Pause(!IsPaused);
|
||||
if (!CanPauseFromInput()) return;
|
||||
if (!IsPaused) Pause(true);
|
||||
}
|
||||
|
||||
public void ContinueFromPause()
|
||||
{
|
||||
if (!IsPaused) return;
|
||||
if (continueCoroutine != null) return;
|
||||
continueCoroutine = StartCoroutine(ContinueFromPauseCoroutine());
|
||||
}
|
||||
|
||||
public void ReplayFromPause()
|
||||
{
|
||||
if (!IsPaused) return;
|
||||
if (continueCoroutine != null)
|
||||
{
|
||||
StopCoroutine(continueCoroutine);
|
||||
continueCoroutine = null;
|
||||
}
|
||||
StartCoroutine(ReplayFromPauseCoroutine());
|
||||
}
|
||||
|
||||
public void ExitFromPause()
|
||||
{
|
||||
if (!IsPaused) return;
|
||||
if (continueCoroutine != null)
|
||||
{
|
||||
StopCoroutine(continueCoroutine);
|
||||
continueCoroutine = null;
|
||||
}
|
||||
StartCoroutine(ExitFromPauseCoroutine());
|
||||
}
|
||||
|
||||
private bool IsGameplaySceneActive()
|
||||
{
|
||||
string sceneName = SceneManager.GetActiveScene().name ?? string.Empty;
|
||||
if (string.Equals(sceneName, gameplaySceneName, StringComparison.OrdinalIgnoreCase)) return true;
|
||||
if (sceneName.IndexOf("gameplay", StringComparison.OrdinalIgnoreCase) >= 0) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool CanPauseFromInput()
|
||||
{
|
||||
if (onlyInGameplayScene && !IsGameplaySceneActive()) return false;
|
||||
if (!requirePlaybackStarted) return true;
|
||||
|
||||
var gm = FindAnyObjectByType<GameManager>();
|
||||
if (gm == null) return false;
|
||||
return gm.PlaybackStarted;
|
||||
}
|
||||
|
||||
private void EnsureOverlayCanvasGroup()
|
||||
{
|
||||
if (overlayRoot == null) return;
|
||||
overlayCanvasGroup = overlayRoot.GetComponent<CanvasGroup>();
|
||||
if (overlayCanvasGroup == null)
|
||||
overlayCanvasGroup = overlayRoot.AddComponent<CanvasGroup>();
|
||||
}
|
||||
|
||||
private void ResolveOverlayRootForPausePrefab()
|
||||
{
|
||||
if (!preferPausePrefabOverWhiteScreen) return;
|
||||
// Prefer the real pause prefab root (contains Continue/Replay/Exit).
|
||||
GameObject pauseRoot = FindPauseMenuRootInScene();
|
||||
if (pauseRoot != null)
|
||||
{
|
||||
overlayRoot = pauseRoot;
|
||||
return;
|
||||
}
|
||||
|
||||
if (overlayRoot == null) return;
|
||||
|
||||
// Legacy setup fallback: PauseManager points to pauseWhiteScreen.
|
||||
if (!string.Equals(overlayRoot.name, legacyWhiteScreenRootName, StringComparison.OrdinalIgnoreCase))
|
||||
return;
|
||||
|
||||
GameObject candidate = FindPauseOverlayCandidate(overlayRoot.transform);
|
||||
if (candidate == null)
|
||||
candidate = FindPauseOverlayCandidate(null);
|
||||
if (candidate != null && candidate != overlayRoot)
|
||||
overlayRoot = candidate;
|
||||
}
|
||||
|
||||
private GameObject FindPauseOverlayCandidate(Transform searchRoot)
|
||||
{
|
||||
Canvas[] canvases = searchRoot != null
|
||||
? searchRoot.GetComponentsInChildren<Canvas>(true)
|
||||
: FindObjectsByType<Canvas>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
||||
|
||||
for (int i = 0; i < canvases.Length; i++)
|
||||
{
|
||||
Canvas canvas = canvases[i];
|
||||
if (canvas == null) continue;
|
||||
|
||||
GameObject go = canvas.gameObject;
|
||||
if (go == null || go == overlayRoot) continue;
|
||||
if (!HasPauseButtons(go)) continue;
|
||||
return go;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private GameObject FindPauseMenuRootInScene()
|
||||
{
|
||||
var all = Resources.FindObjectsOfTypeAll<Transform>();
|
||||
for (int i = 0; i < all.Length; i++)
|
||||
{
|
||||
var t = all[i];
|
||||
if (t == null) continue;
|
||||
if (!t.gameObject.scene.IsValid()) continue;
|
||||
if (!string.Equals(t.name, "pause", StringComparison.OrdinalIgnoreCase)) continue;
|
||||
|
||||
GameObject go = t.gameObject;
|
||||
if (HasPauseButtons(go))
|
||||
return go;
|
||||
}
|
||||
|
||||
// Fallback: any object that contains all three pause action buttons.
|
||||
for (int i = 0; i < all.Length; i++)
|
||||
{
|
||||
var t = all[i];
|
||||
if (t == null) continue;
|
||||
if (!t.gameObject.scene.IsValid()) continue;
|
||||
GameObject go = t.gameObject;
|
||||
if (HasPauseButtons(go))
|
||||
return go;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static bool HasPauseButtons(GameObject root)
|
||||
{
|
||||
if (root == null) return false;
|
||||
Button[] buttons = root.GetComponentsInChildren<Button>(true);
|
||||
bool hasContinue = false;
|
||||
bool hasReplay = false;
|
||||
bool hasExit = false;
|
||||
|
||||
for (int i = 0; i < buttons.Length; i++)
|
||||
{
|
||||
Button b = buttons[i];
|
||||
if (b == null) continue;
|
||||
string n = b.gameObject.name;
|
||||
if (string.Equals(n, "Continue", StringComparison.OrdinalIgnoreCase)) hasContinue = true;
|
||||
else if (string.Equals(n, "Replay", StringComparison.OrdinalIgnoreCase)) hasReplay = true;
|
||||
else if (string.Equals(n, "Exit", StringComparison.OrdinalIgnoreCase)) hasExit = true;
|
||||
}
|
||||
|
||||
return hasContinue && hasReplay && hasExit;
|
||||
}
|
||||
|
||||
private void EnsureOverlayPanelRoot()
|
||||
{
|
||||
if (overlayRoot == null) return;
|
||||
|
||||
if (overlayPanelRoot == null)
|
||||
{
|
||||
var canvases = overlayRoot.GetComponentsInChildren<Canvas>(true);
|
||||
for (int i = 0; i < canvases.Length; i++)
|
||||
{
|
||||
var canvas = canvases[i];
|
||||
if (canvas == null) continue;
|
||||
if (canvas.gameObject == overlayRoot) continue;
|
||||
|
||||
overlayPanelRoot = canvas.GetComponent<RectTransform>();
|
||||
if (overlayPanelRoot != null)
|
||||
break;
|
||||
}
|
||||
|
||||
if (overlayPanelRoot == null)
|
||||
{
|
||||
var rts = overlayRoot.GetComponentsInChildren<RectTransform>(true);
|
||||
for (int i = 0; i < rts.Length; i++)
|
||||
{
|
||||
var rt = rts[i];
|
||||
if (rt == null) continue;
|
||||
if (rt.gameObject == overlayRoot) continue;
|
||||
|
||||
overlayPanelRoot = rt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (overlayPanelRoot == null) return;
|
||||
|
||||
if (overlayPanelCanvasGroup == null)
|
||||
{
|
||||
overlayPanelCanvasGroup = overlayPanelRoot.GetComponent<CanvasGroup>();
|
||||
if (overlayPanelCanvasGroup == null)
|
||||
overlayPanelCanvasGroup = overlayPanelRoot.gameObject.AddComponent<CanvasGroup>();
|
||||
}
|
||||
|
||||
if (IsScaleNearlyZero(panelShownScale))
|
||||
{
|
||||
Vector3 current = overlayPanelRoot.localScale;
|
||||
panelShownScale = IsScaleNearlyZero(current) ? Vector3.one : current;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsScaleNearlyZero(Vector3 scale)
|
||||
{
|
||||
return Mathf.Abs(scale.x) <= 0.0001f
|
||||
&& Mathf.Abs(scale.y) <= 0.0001f
|
||||
&& Mathf.Abs(scale.z) <= 0.0001f;
|
||||
}
|
||||
|
||||
private void SetOverlayVisibleImmediate(bool visible)
|
||||
{
|
||||
if (overlayRoot == null) return;
|
||||
EnsureOverlayCanvasGroup();
|
||||
EnsureOverlayPanelRoot();
|
||||
|
||||
overlayRoot.SetActive(visible);
|
||||
if (overlayCanvasGroup != null)
|
||||
{
|
||||
overlayCanvasGroup.alpha = visible ? 1f : 0f;
|
||||
overlayCanvasGroup.interactable = visible;
|
||||
overlayCanvasGroup.blocksRaycasts = visible;
|
||||
}
|
||||
|
||||
if (overlayPanelCanvasGroup != null)
|
||||
{
|
||||
overlayPanelCanvasGroup.alpha = visible ? 1f : 0f;
|
||||
overlayPanelCanvasGroup.interactable = visible;
|
||||
overlayPanelCanvasGroup.blocksRaycasts = visible;
|
||||
}
|
||||
|
||||
if (overlayPanelRoot != null)
|
||||
{
|
||||
overlayPanelRoot.localScale = visible ? panelShownScale : PanelHiddenScale;
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowOverlayAnimated(bool show)
|
||||
{
|
||||
if (overlayRoot == null)
|
||||
return;
|
||||
|
||||
EnsureOverlayCanvasGroup();
|
||||
if (overlayFadeCoroutine != null)
|
||||
{
|
||||
StopCoroutine(overlayFadeCoroutine);
|
||||
overlayFadeCoroutine = null;
|
||||
}
|
||||
overlayFadeCoroutine = StartCoroutine(FadeOverlayCoroutine(show));
|
||||
}
|
||||
|
||||
private IEnumerator FadeOverlayCoroutine(bool show)
|
||||
{
|
||||
if (overlayRoot == null)
|
||||
yield break;
|
||||
|
||||
EnsureOverlayCanvasGroup();
|
||||
EnsureOverlayPanelRoot();
|
||||
|
||||
if (show && !overlayRoot.activeSelf)
|
||||
overlayRoot.SetActive(true);
|
||||
// Pause entry animation helper may be unavailable in some compile targets.
|
||||
// Keep pause functionality independent from that optional visual effect.
|
||||
|
||||
float startA = overlayCanvasGroup != null ? overlayCanvasGroup.alpha : (show ? 0f : 1f);
|
||||
float startPanelA = overlayPanelCanvasGroup != null ? overlayPanelCanvasGroup.alpha : startA;
|
||||
float targetA = show ? 1f : 0f;
|
||||
Vector3 startScale = overlayPanelRoot != null ? overlayPanelRoot.localScale : panelShownScale;
|
||||
if (show && IsScaleNearlyZero(startScale))
|
||||
startScale = PanelHiddenScale;
|
||||
Vector3 targetScale = show ? panelShownScale : PanelHiddenScale;
|
||||
|
||||
float duration = Mathf.Max(0.01f, overlayFadeDuration);
|
||||
float t = 0f;
|
||||
|
||||
if (show)
|
||||
{
|
||||
if (overlayCanvasGroup != null)
|
||||
{
|
||||
overlayCanvasGroup.interactable = true;
|
||||
overlayCanvasGroup.blocksRaycasts = true;
|
||||
}
|
||||
if (overlayPanelCanvasGroup != null)
|
||||
{
|
||||
overlayPanelCanvasGroup.interactable = true;
|
||||
overlayPanelCanvasGroup.blocksRaycasts = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (overlayCanvasGroup != null)
|
||||
{
|
||||
overlayCanvasGroup.interactable = false;
|
||||
overlayCanvasGroup.blocksRaycasts = false;
|
||||
}
|
||||
if (overlayPanelCanvasGroup != null)
|
||||
{
|
||||
overlayPanelCanvasGroup.interactable = false;
|
||||
overlayPanelCanvasGroup.blocksRaycasts = false;
|
||||
}
|
||||
}
|
||||
|
||||
while (t < duration)
|
||||
{
|
||||
t += Time.unscaledDeltaTime;
|
||||
float k = Mathf.Clamp01(t / duration);
|
||||
if (overlayCanvasGroup != null)
|
||||
overlayCanvasGroup.alpha = Mathf.Lerp(startA, targetA, k);
|
||||
if (overlayPanelCanvasGroup != null)
|
||||
overlayPanelCanvasGroup.alpha = Mathf.Lerp(startPanelA, targetA, k);
|
||||
if (overlayPanelRoot != null)
|
||||
overlayPanelRoot.localScale = Vector3.Lerp(startScale, targetScale, k);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
if (overlayCanvasGroup != null)
|
||||
overlayCanvasGroup.alpha = targetA;
|
||||
if (overlayPanelCanvasGroup != null)
|
||||
overlayPanelCanvasGroup.alpha = targetA;
|
||||
if (overlayPanelRoot != null)
|
||||
overlayPanelRoot.localScale = targetScale;
|
||||
|
||||
if (!show)
|
||||
overlayRoot.SetActive(false);
|
||||
|
||||
overlayFadeCoroutine = null;
|
||||
}
|
||||
|
||||
private IEnumerator ContinueFromPauseCoroutine()
|
||||
{
|
||||
// Start hiding panel, but do not wait before countdown starts.
|
||||
ShowOverlayAnimated(false);
|
||||
|
||||
// Replay 3-2-1-Go immediately on continue click.
|
||||
var gm = FindAnyObjectByType<GameManager>();
|
||||
var ready = gm != null ? gm.readyLetsGo : FindAnyObjectByType<readyLetsGo>();
|
||||
float originalWaitingDuration = 0f;
|
||||
bool waitingDurationOverridden = false;
|
||||
if (ready != null)
|
||||
{
|
||||
// Remove extra idle delay before countdown visuals in continue flow.
|
||||
originalWaitingDuration = ready.waitingDuration;
|
||||
ready.waitingDuration = 0f;
|
||||
waitingDurationOverridden = true;
|
||||
|
||||
try { ready.ResetPlayState(); } catch { }
|
||||
try { ready.PlaySequence(); } catch { }
|
||||
|
||||
int imageCount = ready._321goImages != null ? ready._321goImages.Count : 0;
|
||||
float sequenceDuration = 0.25f
|
||||
+ 0f
|
||||
+ Mathf.Max(0f, imageCount * ready.oneImageDuration)
|
||||
+ 0.15f;
|
||||
if (sequenceDuration > 0f)
|
||||
yield return new WaitForSecondsRealtime(sequenceDuration);
|
||||
}
|
||||
|
||||
if (waitingDurationOverridden && ready != null)
|
||||
{
|
||||
ready.waitingDuration = originalWaitingDuration;
|
||||
}
|
||||
|
||||
// Resume chart + music.
|
||||
Pause(false);
|
||||
continueCoroutine = null;
|
||||
}
|
||||
|
||||
private IEnumerator ReplayFromPauseCoroutine()
|
||||
{
|
||||
SetOverlayVisibleImmediate(false);
|
||||
IsPaused = false;
|
||||
Time.timeScale = 1f;
|
||||
try { OnPauseStateChanged?.Invoke(false); } catch { }
|
||||
|
||||
var bmm = FindAnyObjectByType<BeatmapManager>();
|
||||
if (bmm != null && bmm.assignedSongData != null)
|
||||
{
|
||||
int diff = bmm.assignedDifficulty;
|
||||
if (diff < 0) diff = 0;
|
||||
BeatmapManager.SetPendingSong(bmm.assignedSongData, diff);
|
||||
}
|
||||
|
||||
string current = SceneManager.GetActiveScene().name;
|
||||
yield return LoadSceneAsync(current);
|
||||
}
|
||||
|
||||
private IEnumerator ExitFromPauseCoroutine()
|
||||
{
|
||||
SetOverlayVisibleImmediate(false);
|
||||
IsPaused = false;
|
||||
Time.timeScale = 1f;
|
||||
try { OnPauseStateChanged?.Invoke(false); } catch { }
|
||||
|
||||
yield return LoadSceneAsync(ExitSceneName);
|
||||
}
|
||||
|
||||
private IEnumerator LoadSceneAsync(string sceneName)
|
||||
{
|
||||
AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(sceneName);
|
||||
while (!asyncLoad.isDone)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
private void TryBindButtons(bool force)
|
||||
{
|
||||
if (buttonsBound && !force) return;
|
||||
|
||||
if (onlyInGameplayScene && !IsGameplaySceneActive() && !force)
|
||||
{
|
||||
nextBindRetryTime = Time.unscaledTime + 1f;
|
||||
return;
|
||||
}
|
||||
|
||||
if (pauseTriggerButton == null)
|
||||
{
|
||||
var pauseGO = GameObject.Find(pauseButtonScenePath);
|
||||
if (pauseGO == null)
|
||||
pauseGO = FindByNameInScene("Pause");
|
||||
if (pauseGO != null)
|
||||
pauseTriggerButton = pauseGO.GetComponent<Button>();
|
||||
}
|
||||
|
||||
if (overlayRoot != null)
|
||||
{
|
||||
if (continueButton == null) continueButton = FindButtonInOverlay("Continue");
|
||||
if (replayButton == null) replayButton = FindButtonInOverlay("Replay");
|
||||
if (exitButton == null) exitButton = FindButtonInOverlay("Exit");
|
||||
if (settingsButton == null) settingsButton = FindButtonInOverlay("settings");
|
||||
}
|
||||
|
||||
if (pauseTriggerButton != null)
|
||||
{
|
||||
pauseTriggerButton.onClick.RemoveListener(OnPauseButtonClicked);
|
||||
pauseTriggerButton.onClick.AddListener(OnPauseButtonClicked);
|
||||
}
|
||||
|
||||
if (continueButton != null)
|
||||
{
|
||||
continueButton.onClick.RemoveListener(ContinueFromPause);
|
||||
continueButton.onClick.AddListener(ContinueFromPause);
|
||||
}
|
||||
|
||||
if (replayButton != null)
|
||||
{
|
||||
replayButton.onClick.RemoveListener(ReplayFromPause);
|
||||
replayButton.onClick.AddListener(ReplayFromPause);
|
||||
}
|
||||
|
||||
if (exitButton != null)
|
||||
{
|
||||
exitButton.onClick.RemoveListener(ExitFromPause);
|
||||
exitButton.onClick.AddListener(ExitFromPause);
|
||||
}
|
||||
|
||||
if (settingsButton != null)
|
||||
{
|
||||
settingsButton.onClick.RemoveListener(OnSettingsButtonClicked);
|
||||
settingsButton.onClick.AddListener(OnSettingsButtonClicked);
|
||||
}
|
||||
|
||||
buttonsBound = pauseTriggerButton != null && continueButton != null && replayButton != null && exitButton != null;
|
||||
nextBindRetryTime = Time.unscaledTime + (buttonsBound ? 9999f : 1f);
|
||||
}
|
||||
|
||||
private void OnPauseButtonClicked()
|
||||
{
|
||||
if (!CanPauseFromInput()) return;
|
||||
if (!IsPaused) Pause(true);
|
||||
}
|
||||
|
||||
private void OnSettingsButtonClicked()
|
||||
{
|
||||
if (!IsPaused) return;
|
||||
if (TryOpenExistingSettingsPanel()) return;
|
||||
|
||||
var topController = FindAnyObjectByType<btmandtopController>();
|
||||
if (topController != null)
|
||||
{
|
||||
topController.SendMessage("OnSettingsNavClicked", SendMessageOptions.DontRequireReceiver);
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.LogWarning("[PauseManager] Settings button clicked, but no settings panel source was found.");
|
||||
}
|
||||
|
||||
private bool TryOpenExistingSettingsPanel()
|
||||
{
|
||||
var settingsPanels = Resources.FindObjectsOfTypeAll<ui_Panel_Setting>();
|
||||
for (int i = 0; i < settingsPanels.Length; i++)
|
||||
{
|
||||
ui_Panel_Setting panel = settingsPanels[i];
|
||||
if (panel == null) continue;
|
||||
GameObject go = panel.gameObject;
|
||||
if (go == null || !go.scene.IsValid()) continue;
|
||||
|
||||
go.SetActive(true);
|
||||
go.transform.SetAsLastSibling();
|
||||
|
||||
CanvasGroup cg = go.GetComponent<CanvasGroup>();
|
||||
if (cg != null)
|
||||
{
|
||||
cg.interactable = true;
|
||||
cg.blocksRaycasts = true;
|
||||
}
|
||||
|
||||
UI_SettingsPanelEnterAnim enterAnim = go.GetComponent<UI_SettingsPanelEnterAnim>();
|
||||
if (enterAnim != null) enterAnim.Play();
|
||||
return true;
|
||||
}
|
||||
|
||||
GameObject byName = FindByNameInScene("ui_Panel_Setting");
|
||||
if (byName != null)
|
||||
{
|
||||
byName.SetActive(true);
|
||||
byName.transform.SetAsLastSibling();
|
||||
UI_SettingsPanelEnterAnim enterAnim = byName.GetComponent<UI_SettingsPanelEnterAnim>();
|
||||
if (enterAnim != null) enterAnim.Play();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private Button FindButtonInOverlay(string buttonName)
|
||||
{
|
||||
if (overlayRoot == null || string.IsNullOrEmpty(buttonName)) return null;
|
||||
|
||||
var buttons = overlayRoot.GetComponentsInChildren<Button>(true);
|
||||
for (int i = 0; i < buttons.Length; i++)
|
||||
{
|
||||
var b = buttons[i];
|
||||
if (b == null) continue;
|
||||
if (string.Equals(b.gameObject.name, buttonName, StringComparison.OrdinalIgnoreCase))
|
||||
return b;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private GameObject FindByNameInScene(string name)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name)) return null;
|
||||
|
||||
var all = Resources.FindObjectsOfTypeAll<Transform>();
|
||||
for (int i = 0; i < all.Length; i++)
|
||||
{
|
||||
var t = all[i];
|
||||
if (t == null) continue;
|
||||
if (!string.Equals(t.name, name, StringComparison.OrdinalIgnoreCase)) continue;
|
||||
if (t.gameObject.scene.IsValid())
|
||||
return t.gameObject;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user