关于Loading页的混合加载
上文我们聊了Loading页实现场景切换的功能。 细心的同学可能已经发现了,loading页加载场景时加载的都是场景内的资源,也就是场景中存在的资源。如果我们有些资源来源于本地即时加载或是来自于网络,也想与场景内资源一起通过loading页面加载怎么办呢? 其实也很好解决,只需要我们将loading页改造为分步加载即可。
思路及原理
有两种实现方案:
- 所有场景的网络资源统一在loading场景中管理,在切换到不同场景时使用不同的网络数据与本地资源加载做步骤组合。优点是所有资源统一管理修改,查找方便。缺点是当场景、资源过多时会非常臃肿。
- 从loading场景切换到目标场景时,不释放loading场景,在目标场景中完成网络资源加载逻辑,并通过劫持loading中的方法,与加载步骤进行组合。当完成所有资源加载后,释放Loading场景中的资源。优点是资源加载逻辑在相关的场景中实现,逻辑合理。缺点是不好统一管理。
其实这两种方法实现起来都差不多,本篇实现的是第二种方式。
首先将资源拆成几个step,然后按step逐个加载,并显示相关提示
具体步骤
还没整理完比较糙。3号之前整理完
1, 实现Loading页面和场景加载功能
这部分我已经实现,请你移步查看这篇文章,并确保已经实现
Loading页实现场景切换
2, 对Loading页面改造
using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using System;
using mLib;
public class Loading_Controller : MonoBehaviour
{
private AsyncOperation asyncOperation;
void Start()
{
// 启动异步加载
StartCoroutine(this.AsyncLoading());
}
IEnumerator AsyncLoading()
{
this.asyncOperation= SceneManager.LoadSceneAsync((string)SceneController.sceneNames[SceneController.sceneIndex]);
//终止自动转换场景
this.asyncOperation.allowSceneActivation = false;
yield return asyncOperation;
}
// 设置总步数
public static float custom_totalStep = 1f;
// 当前执行的step
private float custom_currentStep = 1f;
// 当前资源的文字提示
public static string progressDetailsTxt = "Local Resources";
void Update()
{
// anther way: 1f / operation.progress + custom_currentStep
this.view.loadingUIController.SetStep(custom_totalStep, this.custom_currentStep, progressDetailsTxt);
// 当场景内资源加载进度大于0.9 即是完成加载,完成加载step 1
if (this.asyncOperation.progress >= 0.9f)
{
if (custom_totalStep > 1f)
{
DontDestroyOnLoad(this.view.gameObject);
}
// 关闭多余的相机 todo 还有个envent
this.view.mainCamera.gameObject.SetActive(false);
// 允许切换
this.operation.allowSceneActivation = true;
}
}
private void OnDestroy()
{
// 复位
// Loading_Controller.custom_totalStep = 1f;
Loading_Controller.progressDetailsTxt = "Local Resources";
}
/// <summary>
/// 1 设置静态变量 custom_totalStep的值
/// 2 添加 OnCustomLoadingFinished的方法
/// 3 通过 CustomLoading执行加载
/// </summary>
/// <param name="detialsTxt"></param>
/// <param name="loadingAction"></param>
public void CustomLoading(string detialsTxt, Action loadingAction = null)
{
Loading_Controller.progressDetailsTxt = detialsTxt;
this.custom_currentStep += 1f;
loadingAction?.Invoke();
// 当执行结束后,卸载当前页面
if (Loading_Controller.custom_totalStep == this.custom_currentStep)
{
StartCoroutine(mTools.WaitForSecondsDo(1f, () => { }, () =>
{
this.OnCustomLoadingFinished?.Invoke();
Destroy(gameObject);
}));
}
}
public Action OnCustomLoadingFinished;
#endregion
}
改造SceneController
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using System;
public static class SceneController
{
// public static string[] sceneNameList = { "Loading", "TestScene" };
public static ArrayList sceneNames = new ArrayList() {
"Structure",
"RobotCount",
"RobotShow",
"Monitor",
};
public static string LoadingSceneName = "Loading";
// public static
public static int sceneIndex = -1;
// Update is called once per frame
public static void GoToNextScene()
{
if (SceneController.sceneIndex < SceneController.sceneNames.Count - 1)
{
SceneController.sceneIndex++;
GoToSceneByIndex(SceneController.sceneIndex);
// SceneManager.LoadScene((string)SceneController.sceneNames[SceneController.sceneIndex]);
}
}
public static Action AfterGoToScene;
public static void GoToPrevScene()
{
if (SceneController.sceneIndex > 0)
{
SceneController.sceneIndex--;
GoToSceneByIndex(SceneController.sceneIndex);
}
}
/// <summary>
/// goto the scene if finded name in scenelist,atherwase reopen current scene
/// </summary>
/// <param name="sceneName"></param>
public static void GoToSceneByName(string sceneName)
{
if (SceneController.sceneNames.Contains(sceneName))
{
GoToSceneByIndex(SceneController.sceneNames.IndexOf(sceneName));
}
}
public static void GoToSceneByIndex(int sceneIndex)
{
if (SceneController.sceneIndex >= 0 && SceneController.sceneIndex < SceneController.sceneNames.Count)
{
SceneController.sceneIndex = sceneIndex;
// 设置总加载量和detailstxt
Loading_Controller.custom_totalStep = (string)SceneController.sceneNames[SceneController.sceneIndex] switch
{
"Monitor" => 6f,
_ => 1f,
};
SceneManager.LoadScene(LoadingSceneName);
AfterGoToScene?.Invoke();
}
}
///
public static void UnLoadSceneByName(string sceneName)
{
SceneManager.UnloadSceneAsync(sceneName);
}
public static void UnLoadSceneById(int sceneID)
{
SceneManager.UnloadSceneAsync((string)SceneController.sceneNames[sceneID]);
}
}
调用
切换场景
SceneController.GoToSceneByName("RobotCount");
Loading_Controller.custom_totalStep = 4
场景内加载
this.loading_Controller.CustomLoading("Generating static model");