Unity统一过渡加载界面

最近在研究一些与游戏架构无关,却觉得相当重要的小功能,只有在需要用到的时候想到不如在用之前研究好,这篇文章是个人方法,因为网上实现加载界面的功能的方式很多,全文就当参考了。

前言

        我们在玩游戏时,经常会见到加载界面,或者说几乎没有没有加载界面的游戏。

下面这是堕落之主(我发现最近老是拿它说事)的加载界面,这已经算是比较普通的加载界面了,有一些还会提供游戏提示,背景介绍之类的游戏信息。对于玩家来说,加载界面是“喘息”和“思考”的间隙,而对于游戏工作者,加载界面有更多意义,比如提前异步加载场景避免让玩家看到一个虚空世界,或者别的什么处理。

总之就是向玩家提供信息和为加载提供时间。

 

        我们看到堕落之主的加载界面只有一个图案和一个进度条,这其实也是基本加载界面需要的,当然不可能所有游戏都一样。比如怪猎的加载界面就没有进度条,取而代之的是两个导虫转圈圈。所以只要让玩家看得出来是个加载界面就行了。

        这次的笔记将制作一个只有一个进度条和文本提示的加载界面。并且实现“按任意键继续”的功能。

简单加载界面

外观

        直接上图看看是什么样子的。

它的组件很简单,             

Progress(进度条) 下的fill和Text分别对应控制进度条填充和文本的改变。当然怎么做和命名不是重点,重要的是这些所有内容,或者说这整个加载界面是一个场景Scene。

我将LoadingPanel设置为预制体,并在上面添加一个脚本以实现其功能。

在进行脚本讲解前,我想先说明把整个加载界面独立成场景的想法:

1.方便管理。直接管理对应场景即可,简洁明了。

2.逻辑易实现。很多时候,比如以Panel作为加载界面时,是在当前场景加载到目标场景,也就是说还需要管理加载时当前场景的逻辑,避免BUG。但是先加载到一个统一的场景就可以不管上个场景的逻辑了,这个场景有且只有一个逻辑——加载界面。

脚本

        

using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
/// <summary>
/// 场景加载过渡场景。
/// </summary>
public class LoadPanel : Singleton<LoadPanel>
{
    private const string LoadingSceneName = "Loading";
    private static string TargetScene;//目标场景

    public GameObject fill;
    public GameObject text;
    private void Awake()
    {                
        StartCoroutine(LoadSceneAsync(TargetScene));
    }
    public static void LoadScene(string sceneName)
    {
        TargetScene = sceneName;
        SceneManager.LoadScene(LoadingSceneName,LoadSceneMode.Single);//优先加载Loading场景
    }

    IEnumerator LoadSceneAsync(string sceneName)
    {
        fill.GetComponent<Image>().fillAmount = 0f;

        yield return new WaitForSeconds(0.5f);//等待0.5s先,这很重要
        AsyncOperation operation = SceneManager.LoadSceneAsync(sceneName);
        operation.allowSceneActivation = false;
        
        while (!operation.isDone)
        {
            yield return null;
            if(operation.progress >= 0.9f)
            {
                text.GetComponent<Text>().text = "Press To Continue...";
                fill.GetComponent<Image>().fillAmount = 1f;
                if (Input.anyKeyDown)
                {
                    operation.allowSceneActivation = true;
                }
            }
            else
            {
                fill.GetComponent<Image>().fillAmount = operation.progress;                
            }
        }        
        
    }
}

那我从上到下详细说下这坨代码:

1.这个类继承自Singleton<T>,这是个单例母版类,而它继承自Monobehaviour,只需要将其视为写了一点单例模式的代码的Monobehaviour就行了。这个与正文没什么联系。

2.下面两行是做软编码和声明目标场景。LoadingSceneName是加载界面对应的那个场景,我这里是“Loading”。TargetScene就是接下来要加载的下一个场景。

3.下面两个共有声明是进度条对应的填充和文本。这里我是直接将搭载脚本的物体做成预制体,然后在预制体界面将他们两个赋值。当然其他赋值方式也行。

4.在周期函数Awake里直接进行协程的启动。传入TargetScene作为参数。详细看一下这个协程。首先第一句话就是改变填充量归零。这里我是用Image填充方式做进度条而不是Slider,具体可以看我之前的一篇UI制作相关的文章。

        然后就是异步加载的一般操作,存储操作,将操作允许场景激活设为false,因为我们要实现“按任意键继续”的功能。但是前面这个停留0.5秒很重要,因为如果没有等待,allowSceneActivation将会失效,场景会直接跳转不会停留。这个你等待哪怕一帧都是可以的。具体原因不太清楚,有清楚的请请请告诉我。

        接下来的While中编写了进度同步和功能逻辑。我相信这个逻辑很简单,大家都应该看得懂,那我就说一下为什么要以0.9作为分界点,因为当allowSceneActivation=false时,加载进度只会加载到0.9(0~1)时就会停下,剩下0.1只会在allowSceneActivation=true时加载。所以为了美观,我们在进度加载到0.9时将填充量设为1,即进度条填充满。不然它会剩一小段空的。没到0.9就保持加载进度和填充量一致就好了。

5.最后我们来看静态方法LoadScene,它先是将参数传赋值给目标场景,再用一般方式加载加载界面场景。简单来讲就是,我先把这个脚本的目标场景设置为我想要加载的场景,然后固定地先加载到加载界面这个场景,最后通过那个协程实现加载逻辑。这就是为什么TargetScene要设置为静态的,这是为了确保加载场景不存在时,你可以提前为TargetScene赋值,而在加载场景加载出来后,Awake将直接调用协程从而加载你想要的那个场景,你可以把整个流程视为转乘航班。因为加载场景体量很小,所以不需要异步加载(不会真有人在加载界面放一大堆东西吧?!)。

        这样一来,在其他脚本中,一旦你想加载某个场景,只需要直接调用静态方法LoadScene即可,传入你想加载的那个场景作为参数。这里是名字,当然你想用编号之类的也行。

using UnityEngine;

public class Menu : MonoBehaviour
{
    private const string BattleScene = "Battle";
    
    public void NewGame()
    {
        LoadPanel.LoadScene(BattleScene);
    }
}

这里是一个叫做Menu的脚本,想也知道它是干什么的,NewGame已经与按钮事件绑定,里面只有一句话。就是调用静态方法LoadScene,传入了一个叫做Battle的场景名称。

效果

        

可以看见点击按钮后,显示加载到了加载界面场景,然后从加载界面场景再加载到目标场景。     

这样一来我们就实现了统一加载界面功能,以后需要加载场景只用一个方法即可。如果你想要不同的加载方式可以试试修改,这样仅当参考。  

结语

        这样的场景加载方式是相当较为简单的,所以它也是有很多弊端的,比如加载较小的场景时,如果每个小场景都需要这样跳转等待,那么未免会让人烦躁,最好的是多写几种不同的场景加载方式,让玩家在玩游戏时不至于因加载太多而烦恼。

        这个笔记仅提供思路,希望能有所帮助。

  • 20
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Moweiii

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值