赞
踩
我们玩游戏的时候,在进入游戏或场景切换的时候一般都会有一个loading页面。通过这个Loading可以方便的知道当前加载进度,加载速度,并可以通过一些无耻下流的手段来缓解玩家的不安情绪。
专门建立一个loading的场景,然后每次场景切换时我们都先记录好目标场景的名称或序号,然后先载入loading场景,并在loading场景中加载目标场景的资源并显示出来,当加载完成后,再由loading场景切换到目标场景。这样的好处多多,比如loading页面的内容可以集中管理,甚至是多次复用~
创建一个脚本铭文SceneController。需要注意这个脚本中的类是静态的。这就意味着我们可以在任何脚本中直接调用该脚本中的静态方法。
我在脚本中内置了一些方法,他允许你可以使用更多的体位去切换场景。比如通过场景名称切换,通过场景序号切换,直接按顺序切换上一个/下一个场景等
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using System;
public static class SceneController
{
// 场景列表,这里填写的都是你已经存在的scene 的场景名
public static ArrayList sceneNames = new ArrayList() {
"Structure",
"RobotCount",
"RobotShow",
"Monitor",
};
// 自定义loading名,在这里使用它是因为别的需求,如果你的需求比较简单可以直接写死
public static string LoadingSceneName = "Loading";
// 定义一个回调事件 当完成任何场景切换时触发
public static Action AfterGoToScene;
// 即将切换场景的序号
public static int sceneIndex = -1;
// 根据场景顺序,切换到下一个场景的方法
public static void GoToNextScene()
{
if (SceneController.sceneIndex < SceneController.sceneNames.Count - 1)
{
SceneController.sceneIndex++;
GoToSceneByIndex(SceneController.sceneIndex);
}
}
// 根据场景顺序,切换到上一个场景
public static void GoToPrevScene()
{
if (SceneController.sceneIndex > 0)
{
SceneController.sceneIndex--;
GoToSceneByIndex(SceneController.sceneIndex);
}
}
// 根据场景名称(scene name) 切换到目标场景 (scene index会跟着变动)
/// <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();
}
}
// 根据目标场景名称 注销目标场景,这个只是为了统一管理,因为unity早就内置了方法
public static void UnLoadSceneByName(string sceneName)
{
SceneManager.UnloadSceneAsync(sceneName);
}
// 根据目标场景序号 注销目标场景
public static void UnLoadSceneById(int sceneID)
{
SceneManager.UnloadSceneAsync((string)SceneController.sceneNames[sceneID]);
}
}
首先在编辑器中创建一个scene,起名为Loading。然后分别添加image、text对象。这里我使用的是meshprotext,建议大家都使用这个而不是unity自带的txt。可以有效解决文字失真、锯齿的问题。
点击image查看inspector窗口,将Image中的Image Type设置为Filled,Fill Method设置为Horizontal
在场景中,通过拖拽将txt和image摆成这个样子就完成了
创建一个名为LoadingController.cs的脚本,复制以下代码,保存后将脚本拖到场景中任意物体上。该脚本的作用是当进入loading场景时,开始加载目标场景的资源。捕获加载进度制作进度条,当加载完成后再跳转到目标场景。
```csharp
using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using System;
using mLib;
public class Loading_Controller : MonoBehaviour
{
// 加载进度显示
public TextMeshProUGUI progressText;
// 进度条
public Image progressBar;
// 目标异步场景
private AsyncOperation asyncOperation;
void Start()
{
// 协程启动异步加载
StartCoroutine(this.AsyncLoading());
}
IEnumerator AsyncLoading()
{
this.asyncOperation= SceneManager.LoadSceneAsync((string)SceneController.sceneNames[SceneController.sceneIndex]);
//终止自动切换场景
this.operation.allowSceneActivation = false;
yield return operation;
}
void Update()
{
// 获取加载进度,让进度条动起来
this.SettingLoadingUI(this.asyncOperation.progress);
// 当进度大于0.9时就已经加载完毕
if (this.asyncOperation.progress >= 0.9f)
{
// 允许切换。将在下一帧切换场景
this.operation.allowSceneActivation = true;
}
}
public void SettingLoadingUI(float progress )
{
// 百分比的方式显示进度
this.progressText.text = (progress*100f).ToString() + "%";
// 通过改变image的宽度来实现进度条
this.progressBar.fillAmount = progress;
}
}
点击脚本所在的物体,在他的inspector窗口中找到脚本控件,将之前创建的image,txt拖到控件中的响应位置后保存场景即可
当我们在某个场景中,需要切换到新场景时,那么只需触发相应方法就能实现了。该方法会让你的场景先切换到Loading场景,当目标场景的资源加载完成后再从Loading场景中切换过去
// 切换到目标场景
SceneController.GoToSceneByName("RobotCount");
需要注意的是场景列表中的名称一定是真实有效的,并且确定所有场景都必须已经在biulding settings中已经注册了
public static ArrayList sceneNames = new ArrayList() {
"Structure",
"RobotCount",
"RobotShow",
"Monitor",
};
你可能已经发现。该方法只能加载场景内资源。也就是和场景中存在的资源。如果你有对本地资源、网络资源的加载需求,又或者是混合的加载需求该怎么办呢?
答案是混合加载。只需要将Loading页面扩展一下就可以实现。
相关方法请查看这篇文章unity Loading页面,实现本地、网络资源的混合加载
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。