using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
namespace GameFramework
{
///
/// 场景异步加载器(持久化单例)。带黑色淡入淡出过渡。
/// 场景名可在 Inspector 配置,默认 MainMenu / Gameplay / Scoring。
///
/// 搭建:把 SceneLoader 挂到一个空物体上(放第一个场景 MainMenu 里),
/// 它会 DontDestroyOnLoad。transitionImage 是它子物体 Canvas 上的 Image(全屏黑),
/// Canvas 设为 Screen Space - Overlay、sortingOrder 设很高(如 9999)。
///
public class SceneLoader : PersistentSingleton
{
[Header("过渡")]
[SerializeField] private Image transitionImage;
[SerializeField] private float fadeTime = 1.5f;
[Header("场景名(按你工程里的实际名称填)")]
[SerializeField] private string mainMenuScene = "MainMenu";
[SerializeField] private string gameplayScene = "Gameplay";
[SerializeField] private string scoringScene = "Scoring";
private Color color;
private bool isLoading = false;
public void LoadGameplayScene()
{
// 重置 GameManager 状态
if (GameManager.Instance != null)
{
GameManager.GameState = GameState.Playing;
GameManager.onGameOver = null;
GameManager.onGameWin = null;
}
// 重置 ScoreManager
if (ScoreManager.Instance != null)
ScoreManager.Instance.ResetScore();
// 清理静态事件残留订阅
IndianOceanAssets.Engine2_5D.HealthSystem.onPlayerDamaged = null;
Load(gameplayScene);
}
public void LoadMainMenuScene() => Load(mainMenuScene);
public void LoadScoringScene() => Load(scoringScene);
public void Load(string sceneName)
{
if (isLoading) return;
isLoading = true;
StopAllCoroutines();
StartCoroutine(LoadingCoroutine(sceneName));
}
private IEnumerator LoadingCoroutine(string sceneName)
{
if (transitionImage == null)
{
Debug.LogWarning("[SceneLoader] transitionImage 未赋值! " +
"请在 SceneLoader 子物体上创建 Canvas (Overlay, SortOrder=9999) + 全屏黑色 Image," +
"拖到 SceneLoader 的 transitionImage 字段。");
}
var loadingOperation = SceneManager.LoadSceneAsync(sceneName);
loadingOperation.allowSceneActivation = false;
if (transitionImage != null)
{
transitionImage.gameObject.SetActive(true);
color = transitionImage.color;
color.a = 0f;
// 淡入到黑(LoadSceneAsync 在后台并行加载)
while (color.a < 1f)
{
color.a = Mathf.Clamp01(color.a + Time.unscaledDeltaTime / fadeTime);
transitionImage.color = color;
yield return null;
}
color.a = 1f;
transitionImage.color = color;
// 淡入完成后,确保场景已加载就绪(大多数情况下已经加载好了)
yield return new WaitUntil(() => loadingOperation.progress >= 0.9f);
}
else
{
// 没有过渡图,直接等加载
yield return new WaitUntil(() => loadingOperation.progress >= 0.9f);
}
loadingOperation.allowSceneActivation = true;
// 等待场景切换完全完成(旧场景卸载 + 新场景渲染就绪)
// 没有这一步会在场景交接时闪一帧旧场景的内容
yield return null;
yield return null;
if (transitionImage != null)
{
// 淡出到透明
while (color.a > 0f)
{
color.a = Mathf.Clamp01(color.a - Time.unscaledDeltaTime / fadeTime);
transitionImage.color = color;
yield return null;
}
transitionImage.gameObject.SetActive(false);
}
isLoading = false;
}
}
}