using System; using System.Collections; using Mountools.Tools; using UnityEngine; using UnityEngine.Events; using UnityEngine.SceneManagement; namespace Mountools.LoadingScreen { [DisallowMultipleComponent] #if MT_L_CHINESE [AddComponentMenu("Mountools/加载画面/异步加载画面")] #endif #if MT_L_ENGLISH [AddComponentMenu("Mountools/Loading Screen/Async Loading Screen")] #endif public class LoadingScreen : MonoBehaviour { public static LoadingScreen GetLoadingScreen() { return FindObjectOfType(); } public float loadingStartWaitSeconds = 2; public float loadingDoneWaitSeconds = 2; public float fakeLoadingRate = 0.1f; private Coroutine _loadSceneCoroutine; public float progress; public bool isLoading; public string loadingSceneName; public UnityEvent onLoad; public UnityEvent onLoading; public UnityEvent onLoaded; public static void LoadScene(int sceneIndex, LoadSceneMode mode = LoadSceneMode.Single, bool fakeLoad = false) { LoadScene(SceneManager.GetSceneAt(sceneIndex).name, mode, fakeLoad); } public static void LoadScene(string sceneName, LoadSceneMode mode = LoadSceneMode.Single, bool fakeLoad = false) { var loadingScreen = GetLoadingScreen(); if (loadingScreen == null) { Debug.LogWarning( MountoolsLanguage.Lang( "场景内没有加载画面!", "There are no Loading Screen in the scene!" )); SceneManager.LoadScene(sceneName, mode); } else { loadingScreen.Load(sceneName, mode, fakeLoad); } } private void Load(string sceneName, LoadSceneMode mode = LoadSceneMode.Single, bool fakeLoad = false) { loadingSceneName = sceneName; if (_loadSceneCoroutine == null) { _loadSceneCoroutine = StartCoroutine(LoadSceneAsync(sceneName, mode, fakeLoad)); } else { Debug.LogWarning( MountoolsLanguage.Lang("请勿重复加载场景!", "Do not load the scene repeatedly!") ); } } private IEnumerator LoadSceneAsync(string sceneName, LoadSceneMode mode, bool fakeLoad) { // 设置状态,调用事件 isLoading = true; onLoad.Invoke(sceneName); // 等待动画播放 yield return new WaitForSecondsRealtime(loadingStartWaitSeconds); // 开始加载 var loadAsync = SceneManager.LoadSceneAsync(sceneName, mode); loadAsync.allowSceneActivation = false; progress = 0; if (fakeLoad) { // 假加载 (测试用) while (progress < 0.9f) { progress += 0.1f; onLoading.Invoke(progress); yield return new WaitForSecondsRealtime(fakeLoadingRate); } } else { // 真加载 while (progress < 0.86f) { progress = (float) Math.Round(Mathf.Lerp(progress, loadAsync.progress, 0.2f), 3); onLoading.Invoke(progress); yield return new WaitForEndOfFrame(); } // 等待完全加载 while (loadAsync.progress < 0.9f) { yield return new WaitForEndOfFrame(); } // 完全加载后,进入新场景 loadAsync.allowSceneActivation = true; // 继续播放剩余 10% 的动画 while (progress < 0.99f) { progress = (float) Math.Round(Mathf.Lerp(progress, 1f, 0.2f), 3); onLoading.Invoke(progress); yield return new WaitForEndOfFrame(); } } // 进度条设置为 100% progress = 1; // 执行加载后事件 onLoaded.Invoke(); // 等待退出动画的播放 yield return new WaitForSecondsRealtime(loadingDoneWaitSeconds); // 设置加载完成 isLoading = false; } private void Start() { DontDestroyOnLoad(gameObject); onLoaded.AddListener(() => { _loadSceneCoroutine = null; }); } } }