前言

   该文档为《Unity游戏开发文档(3):Dancing Line》的附属文档,亦可看作是单独的技术总结文档。


目录

  • 综述
  • 异步加载场景
  • 显示加载进度
  • 最终效果
  • 参考资料






综述

当游戏需要从一个 场景(Sence) 跳转到另外一个场景时,如果下一个场景需要加载的资源很多,那么游戏会便会卡在上一个场景不动,直到下一个场景完成加载后游戏才会进入。对于玩家来说,每次在加载新场景的时候都要等一大段时间有什么都做不了,是很令人不爽的,游戏体验也大打折扣了。

所以基本所有的游戏在加载大场景之前,都会先让游戏进入一个可以瞬间完成加载的小场景中,在小场景中显示加载进度条,或者播放一些小动画,更有甚者会内嵌一个小游戏,同时并行地加载大场景。当大场景完成加载后,游戏便跳出当前的小场景,进入到大场景中,继续执行正常的游戏流程。这样便可以避免等待场景切换带来的低游戏体验了。


异步加载场景

异步加载场景的逻辑如下:

  1. 假设有三个场景,A场景是游戏当前所在场景,B场景是过渡场景,C场景是最终需要进入的场景。
  2. 在A场景时,我们首先加载并进入到B场景。
  3. 随后在B场景中,我们创建一个协程,并命令协程加载C场景。在C场景加载的这段时间里,游戏会继续执行B场景的游戏逻辑。
  4. C场景完成加载后会协程返回到B场景的主线逻辑,B场景的主线逻辑得知协程退出后,会立刻进入C场景。
  5. 游戏开始执行C场景逻辑。

Dancing Line 中,我们需要做的是从 Menu 场景经过 Load 场景的过渡,进入到 Game场景。具体的代码实现如下:

  • 在A场景中,由于我们是通过点击按钮触发场景切换,所以代码还包含了按钮监听点击事件的逻辑
using UnityEngine.SceneManagement;

private Button button;

void Start() {
    button = transform.GetComponent<Button>();
    button.onClick.AddListener(LoadGameScene);
} 

public void LoadGameScene() {
    Destroy(this);
    SceneManager.LoadScene(load_scene);				// Load the "load_scene" scene
}
  • B场景加载C场景的实现代码
using UnityEngine.SceneManagement;

void Start () {
    StartCoroutine(LoadScene());                    // Begin to asynchronous load game scene
}

IEnumerator LoadScene()                             // Asynchronous load game scene
{
    async = SceneManager.LoadSceneAsync(GlobalData.game_scene);
    yield return async;
}


显示加载进度

在过渡场景中游戏应该做些什么来为玩家排闷解乏,那就需要开发者发挥各自的想象力了,萝卜青菜各有所爱。在这里我们会介绍最常见也是最基本的形式,即为玩家显示加载百分比进度以及进度条。

百分比进度可以用 Unity GUI 内置的 TextTextMeshPro 组件实现,我们在每一帧获取场景当前的加载进度,然后把数值更新到文本内容上即可。

unity外部资源异步加载 unity异步加载原理_加载


红框处即是用于显示进度的组件,由于未进行游戏,所以没有对应的信息显示  

进度条可以用 Unity GUI 内置的 Image 组件实现。我们首先需要准备长条形的图片,把它设为 Unity Image。然后在每一帧,通过我们获取得到的场景加载进度来设置图片的可显示部分,即可实现进度条功能。

unity外部资源异步加载 unity异步加载原理_unity3d_02


红框处即是进度条组件 

下方是具体的代码实现:

private int progress = 0;
private Image progress_bar;
private TextMeshProUGUI progress_text;
private AsyncOperation async = null;


void OnGUI() {
    progress_text.text = progress + "%";            // Update the text for displaying realtime progress of scene loading
    progress_bar.fillAmount = progress / 100f;      // Update the progress bar base on the loading progress
    if (progress == 100) {
        progress_text.text = "OK";                  // Display "OK" when scene loading is complete 
    }
}

void Start () {
    StartCoroutine(LoadScene());                    // Begin to asynchronous load game scene
}

void Update() {
    progress = (int)(async.progress * 100);
}


最终效果

unity外部资源异步加载 unity异步加载原理_游戏开发_03

额…要加载的游戏场景不是很大,一下子就完成加载了,所以最终我们只能看到过渡的场景闪了一下就跳到游戏场景了。


参考资料

异步加载游戏场景与异步加载游戏资源进度条: http://www.xuanyusong.com/archives/1427 Unity 中场景切换: LoadSceneAsync出现的问题: SceneManager.LoadScene调用后新场景会变暗的问题: