1、使用异步加载场景:
AsyncOperation op = SceneManager.LoadSceneAsync(scene); //异步加载场景,速度很快
2、用协程更新进度条:
public Slider progressBar; //场景中显示进度的滑动条
private IEnumerator LoadingScene(int scene)
{
int displayBar = 0; //进度条已经显示的加载值、展现给玩家的当前进度;
int targetBar; //进度条需要达到的目标值
...
while (displayBar < targetBar) //进度条显示值小于进度条目标值,逐渐增大
{
++displayBar;
progressBar.value = displayBar / 100;
yield return new WaitForEndOfFrame();
}
...
}
3、完整功能代码:
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class LoadGame : MonoBehaviour
{
public Slider progressBar;
void Start()
{
StartCoroutine(LoadingScene(2));
}
private IEnumerator LoadingScene(int scene)
{
int displayBar = 0; //进度条已经显示的加载值、展现给玩家的当前进度;
int targetBar; //进度条需要达到的目标值
AsyncOperation op = SceneManager.LoadSceneAsync(scene);
//限制场景加载程度,不允许立马切换场景,op.progress也只会到达/停在0.899f处
op.allowSceneActivation = false;
//根据场景加载程度,设置显示进度条,使进度条慢慢加载
while (op.progress < 0.9f)
{
targetBar = (int)op.progress * 100;
while (displayBar < targetBar)
{
++displayBar;
progressBar.value = displayBar / 100;
yield return new WaitForEndOfFrame();
}
}
targetBar = 100; //设置进度条目标显示值可到100%
while (displayBar < targetBar) //进度条显示值小于进度条目标值,逐渐增大
{
++displayBar;
progressBar.value = displayBar / 100;
yield return new WaitForEndOfFrame();
}
op.allowSceneActivation = true; //进度条加载完全,切换场景
}
}
4、优化改进:
存在问题:无法控制进度条的加载速度,依旧存在 小场景加载过快,用户体验感差的问题。
优化改进:设置进度条更新幅度大小,由原来的每帧+1,
改为增加一定的时间帧:Time.deltaTime * speed
public Slider progressBar;
public int speed = 2; //自定义进度条速度
private IEnumerator LoadingScene(int scene)
{
float displayBar = 0;
float targetBar;
...
while (displayBar < targetBar)
{
//++displayBar;
//progressBar.value = displayBar / 100;
displayBar += Time.deltaTime * speed;
progressBar.value = displayBar;
yield return new WaitForEndOfFrame();
}
...
}
5、优化后完整代码:
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class LoadGame : MonoBehaviour
{
public Slider progressBar;
public int speed = 2;
void Start()
{
StartCoroutine(LoadingScene(2));
}
private IEnumerator LoadingScene(int scene)
{
float displayBar = 0;
float targetBar;
AsyncOperation op = SceneManager.LoadSceneAsync(scene);
op.allowSceneActivation = false;
while (op.progress < 0.9f)
{
targetBar = op.progress;
while (displayBar < targetBar)
{
displayBar += Time.deltaTime * speed;
progressBar.value = displayBar;
yield return new WaitForEndOfFrame();
}
}
targetBar = 1;
while (displayBar < targetBar)
{
displayBar += Time.deltaTime * speed;
progressBar.value = displayBar;
yield return new WaitForEndOfFrame();
}
op.allowSceneActivation = true;
}
}
6、二次优化:
存在问题:
1、由于协程加载不稳定情况,进度条加载会出现卡顿或过快的情况。
2、直接使用Time.deltaTime*speed作为进度条增幅值,受机器和项目大小影响较大,并没有多方便人为设置调整。
优化改进:将进度条数值修改的语句,放到主线程执行调用。
将进度条显示的值displayBar,转为int值,百分制,固定值增幅;
private IEnumerator StartLoading_4(int scene)
{
int displayBar = 0; //改成int型
int targetBar; //改成int型
while (op.progress < 0.9f)
{
targetBar= (int)op.progress * 100; //改成百分制
while (displayBar < targetBar)
{
++displayBar ; //固定值增加
SetBarValue(displayBar ); //进度条修改放进主进程中
yield return new WaitForEndOfFrame();
}
targetBar= 100; //改成百分制
while (displayBar < targetBar)
{
++displayBar ; //固定值增加
SetBarValue(displayBar ); //放进主进程中修改
yield return new WaitForEndOfFrame();
}
}
}
/// <summary>
/// 主线程修改进度条,直接协程里修改会显示卡顿或过快
/// </summary>
/// <param name="v"></param>
private void SetBarValue(float v)
{
processBar.value = v / 100;
}
7、完整功能代码:
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class LoadGame : MonoBehaviour
{
public Slider processBar;
void Start()
{
StartCoroutine(StartLoading_4(2));
}
private IEnumerator StartLoading_4(int scene)
{
int displayBar = 0;
int targetBar;
AsyncOperation op = SceneManager.LoadSceneAsync(scene);
op.allowSceneActivation = false;
while (op.progress < 0.9f)
{
targetBar = (int)op.progress * 100;
while (displayBar < targetBar)
{
++displayBar;
SetBarValue(displayBar);
yield return new WaitForEndOfFrame();
}
}
targetBar = 100;
while (displayBar < targetBar)
{
++displayBar;
SetBarValue(displayBar);
yield return new WaitForEndOfFrame();
}
op.allowSceneActivation = true;
}
private void SetBarValue(float v)
{
processBar.value = v / 100;
}
}