Files
gold_dolphin/unity/Assets/UI/SceneLoader.cs
T
2026-07-01 02:03:14 +08:00

99 lines
3.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
namespace GameFramework
{
/// <summary>
/// 场景异步加载器(持久化单例)。带黑色淡入淡出过渡。
/// 场景名可在 Inspector 配置,默认 MainMenu / Gameplay / Scoring。
///
/// 搭建:把 SceneLoader 挂到一个空物体上(放第一个场景 MainMenu 里),
/// 它会 DontDestroyOnLoad。transitionImage 是它子物体 Canvas 上的 Image(全屏黑),
/// Canvas 设为 Screen Space - Overlay、sortingOrder 设很高(如 9999)。
/// </summary>
public class SceneLoader : PersistentSingleton<SceneLoader>
{
[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() => 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);
}
}
}
}