一, 前景
如果要切换到的Scene, 资源比较多,最好是给玩家一个进度面板.这样不至于让玩家觉得"卡"的错觉.并且了解当前加载的情况.
二, 关键技术点讲解
Ⅰ, SceneManager.LoadSceneAsync
异步加载Scene,返回 AsyncOperation
Ⅱ, AsyncOperation
三, 实践
Ⅰ, 设计原理
1, 有A场景切换到B场景.
2, 设计一个进度面板的预设体.如下
3, 在A场景中,放一个跳转的按钮, 点击之后. 动态加载进度面板并显示.
4, 进度面板,负责加载B场景 , 先设置allowSceneActivation = false. 我需要将B加载好后再显示.
5, 当进度加载到90%的时候,直接设置成100%, 因为官方文档:
Ⅱ, 代码部分
1, 在A场景Canvas中挂载脚本:Jump2B
using Common;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
/// <summary>
/// 跳转至B场景,第二个场景
/// </summary>
public class Jump2B : MonoBehaviour
{
private Button btnJump;
private SceneProgress sceneProgress;
void Start()
{
this.btnJump = this.gameObject.transform.Find("BtnJump").GetComponent<Button>();
this.ListernerClick(true);
}
private void ListernerClick(bool isAdd)
{
if (isAdd)
{
this.btnJump.onClick.AddListener(this.OnClick);
}
else
{
this.btnJump.onClick.RemoveListener(this.OnClick);
}
}
private void OnClick()
{
this.btnJump.gameObject.SetActive(false);
GameObject pregressPanel = ResourcesManager.Load<GameObject>("PregressPrefab");//获得进度预制体
GameObject panel = Instantiate(pregressPanel, this.transform);
this.sceneProgress = panel.AddComponent<SceneProgress>();
StartCoroutine(this.GoBScene());
}
/// <summary>
/// 跳转到B场景
/// </summary>
/// <returns></returns>
private IEnumerator GoBScene()
{
yield return 1;//等到1帧, 让sceneProgress的处理Start
//开始跳转到B场景
this.sceneProgress.JumpToNextScene(SceneManager.GetActiveScene().buildIndex + 1, "正在加载B场景");
}
private void OnDestroy()
{
this.ListernerClick(false);
if (this.sceneProgress != null)
{
Destroy(this.sceneProgress.gameObject);//删除进度面板
this.sceneProgress = null;
}
StopAllCoroutines();
}
}
2, 实现加载进度面板脚本:SceneProgress, 由代码添加到加载面板上(如上代码), 代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
/// <summary>
/// 加载scene进度面板
/// </summary>
public class SceneProgress : MonoBehaviour
{
private Slider sliderProgress;
private Text txtContent;
private Text txtProgress;
private AsyncOperation operation;
void Start()
{
this.sliderProgress = this.gameObject.transform.Find("Progress").GetComponent<Slider>();
this.txtContent = this.gameObject.transform.Find("TxtContent").GetComponent<Text>();
this.txtProgress = this.gameObject.transform.Find("Progress/Handle Slide Area/Handle/TxtProgress").GetComponent<Text>();
}
public void JumpToNextScene(int sceneIndex, string tip = null)
{
if (SceneManager.GetActiveScene().buildIndex == sceneIndex)
{
return;
}
if (tip == null || tip.Trim() == string.Empty)
{
this.txtContent.text = "";
}
else
{
this.txtContent.text = tip;
}
StartCoroutine(this.JumpScene(sceneIndex));//启动协程开始加载
}
private IEnumerator JumpScene(int sceneIndex)
{
this.operation = SceneManager.LoadSceneAsync(sceneIndex, LoadSceneMode.Single);
this.operation.allowSceneActivation = false;//进度条读完之前,不要显示sceneIndex这个scene
while (!this.operation.isDone)
{
if (this.operation.progress >= 0.9f)
{
yield return new WaitForSeconds(0.1f);//等待0.1s
this.sliderProgress.value = 1;
this.txtProgress.text = "100%";
yield return new WaitForSeconds(0.35f);//等待0.35s
this.operation.allowSceneActivation = true;
}
else
{
this.sliderProgress.value = this.operation.progress;
this.txtProgress.text = $"{Mathf.Floor(this.operation.progress * 100)}%";
}
yield return null;
}
}
private void OnDestroy()
{
StopAllCoroutines();
}
}
四, 运行结果
目前还在A, 在跳转到B之前的截图.