summaryrefslogtreecommitdiff
path: root/Assets/Mountools/Extends/LoadingScreen/LoadingScreen.cs
blob: a83ae0e0446223462822411741921bbb617351c6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
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<LoadingScreen>();
        }

        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<string> onLoad;
        public UnityEvent<float> 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;
            });
        }
    }
}