unity3d中制作loading场景进度条所遇到的问题loadlevelasync,asyncoperation

mimime mimime     2022-08-24     411

关键词:

背景

通常游戏的主场景包含的资源较多,这会导致加载场景的时间较长。为了避免这个问题,可以首先加载Loading场景,然后再通过Loading场景来加载主场景。因为Loading场景包含的资源较少,所以加载速度快。在加载主场景的时候一般会在Loading界面中显示一个进度条来告知玩家当前加载的进度。在Unity中可以通过调用Application.LoadLevelAsync函数来异步加载游戏场景,通过查询AsyncOperation.progress的值来得到场景加载的进度。

尝试——遇到问题

第一步当加载完Loading场景后,调用如下的LoadGame函数开始加载游戏场景,使用异步加载的方式加载场景1(Loading场景为0,主场景为1),通过Unity提供的Coroutine机制,我们可以方便的在每一帧结束后调用SetLoadingPercentage函数来更新界面中显示的进度条的数值。

public void LoadGame() {
    StartCoroutine(StartLoading_1(1));
}

private IEnumerator StartLoading_1(int scene) {
    AsyncOperation op = Application.LoadLevelAsync(scene);
    while(!op.isDone) {            
        SetLoadingPercentage(op.progress * 100);
        yield return new WaitForEndOfFrame();
    }        
}

最后进度条的效果显示如下:

技术分享

进度条并没有连续的显示加载的进度,而是停顿一下切换一个数字,再停顿一下切换一个数子,最后在没有显示100%就情况下就切换到主场景了。究其原因在于Application.LoadLevelAsync并不是真正的后台加载,它在每一帧加载一些游戏资源,并给出一个progress值,所以在加载的时候还是会造成游戏卡顿,AsyncOperation.progress的值也不够精确。当主场景加载完毕后Unity就自动切换场景,所以上述代码中的while循环体内的代码是不会被调用的,导致进度条不会显示100%。

修补——100%完成

为了让进度条能显示100%,取巧一点的办法是将AsyncOperation.progress的值乘上2,这样当加载到50%的时候界面上就显示100%了。缺点是当界面上显示100%的时候,用户还要等待一段时间才会进入游戏。其实Unity提供了手动切换场景的方法,把AsyncOperation.allowSceneActivation设为false就可以禁止Unity加载完毕后自动切换场景,修改后的StartLoading_2代码如下:

// this function is not work
private IEnumerator StartLoading_2(int scene) {
    AsyncOperation op = Application.LoadLevelAsync(scene);
    op.allowSceneActivation = false;
    while(!op.isDone) {
        SetLoadingPercentage(op.progress * 100);
        yield return new WaitForEndOfFrame();
    }
    op.allowSceneActivation = true;   
}

我们首先将AsyncOperation.allowSceneActivation设为false,当加载完成后再设为true。代码看上去没有错,但是执行的结果是进度条最后会一直停留在90%上,场景不会切换。通过打印log发现AsyncOperation.isDone一直为falseAsyncOperation.progress的值增加到0.9后就保持不变了,也就是说场景永远不会被加载完毕。

技术分享

在这个帖子中找到了答案,原来把allowSceneActivation设置为false后,Unity就只会加载场景到90%,剩下的10%要等到allowSceneActivation设置为true后才加载,这不得不说是一个坑。所以代码改为如下。当AsyncOperation.progress到达0.9后,就直接把进度条的数值更新为100%,然后设置AsyncOperation.allowSceneActivationture,让Unity继续加载未完成的场景。

private IEnumerator StartLoading_3(int scene) {
    AsyncOperation op = Application.LoadLevelAsync(scene);
    op.allowSceneActivation = false;
    while(op.progress < 0.9f) {
        SetLoadingPercentage(op.progress * 100);
        yield return new WaitForEndOfFrame();
    }
    SetLoadingPercentage(100);
    yield return new WaitForEndOfFrame();
    op.allowSceneActivation = true;   
}

最后的效果如下:

技术分享

打磨——增加动画

上述的进度条虽然解决了100%显示的问题,但由于进度条的数值更新不是连续的,所以看上去不够自然和美观。为了看上去像是在连续加载,可以每一次更新进度条的时候插入过渡数值。这里我采用的策略是当获得AsyncOperation.progress的值后,不立即更新进度条的数值,而是每一帧在原有的数值上加1,这样就会产生数字不停滚动的动画效果了,迅雷中显示下载进度就用了这个方法。

private IEnumerator StartLoading_4(int scene) {
    int displayProgress = 0;
    int toProgress = 0;
    AsyncOperation op = Application.LoadLevelAsync(scene);
    op.allowSceneActivation = false;
    while(op.progress < 0.9f) {
        toProgress = (int)op.progress * 100;
        while(displayProgress < toProgress) {
            ++displayProgress;
            SetLoadingPercentage(displayProgress);
            yield return new WaitForEndOfFrame();
        }
    }

    toProgress = 100;
    while(displayProgress < toProgress){
        ++displayProgress;
        SetLoadingPercentage(displayProgress);
        yield return new WaitForEndOfFrame();
    }
    op.allowSceneActivation = true;
}

displayProgress用来记录要显示在进度条上的数值,最后进度条的动画如下:

技术分享

对比第一种的进度条

技术分享

总结

如果在加载游戏主场景之前还需要解析数据表格,生成对象池,进行网络连接等操作,那么可以给这些操作赋予一个权值,利用这些权值就可以计算加载的进度了。如果你的场景加载速度非常快,那么可以使用一个假的进度条,让玩家看上几秒钟的loading动画,然后再加载场景。总之进度条虽然小,但要做好也是不容易的。

 

 

https://docs.unity3d.com/ScriptReference/SceneManagement.SceneManager.LoadSceneAsync.html

https://docs.unity3d.com/ScriptReference/AsyncOperation.html

AsyncOperation

 

Description

Asynchronous operation coroutine.

You can yield until asynchronous operation continues, or manually check whether it‘s done (isDone) or progress (progress).

See Also: SceneManager.LoadSceneAsync, AssetBundle.LoadAsync.

Variables

allowSceneActivation Allow scenes to be activated as soon as it is ready.
isDone Has the operation finished? (Read Only)
priority Priority lets you tweak in which order async operation calls will be performed.
progress What‘s the operation‘s progress. (Read Only)

 



纯css3制作圆形进度条所遇到的问题

  近日在开发的页面中,需要制作一个动态的圆形进度条,首先想到的是利用两个矩形,宽等于直径的一半,高等于直径,两个矩形利用浮动贴在一起,设置overflow:hidden属性,作为盒子,内部有一个与其宽高相等的子盒子,... 查看详情

unity简单的进度条实现(代码片段)

制作进度条所需的资源:用以载入进度条显示的场景进度条背景以及进度条本身(颜色区别)展示百分制进度情况的Text文本需要载入的场景(这里使用的是自带场景)载入时的场景布局:要将Load的ImageType修改为Filled,FillMethod修... 查看详情

在unity3d里怎么做进度条

...Scene场景,用于处理加载进度条。二、导入NGUI资源包,在Unity3D菜单栏中选中NGUI-Open-PrefabToolbar,在PrefabToolbar窗口中,选中Control-ColoredProgressBar拖拽至Hierarchy面板,修改名字为”Loading“。三、在Hierarchy面板,Loading添加子物体Label... 查看详情

unity3d中怎么制作关卡载入进度条

1.新建两个场景,保存为level1和level22.将图片素材放进工程文件中,分别作为关卡背景、进度条背景和进度条前景3.创建C#脚本,取名Life4.打开脚本,加入如图所示代码5.将脚本拖拽到摄像机上,将三张图片对号入座到图片变量中6.... 查看详情

unity3d___ugui中如何创建loading...进度条

http://blog.sina.com.cn/s/blog_e82e8c390102wh2z.html 实现方法:通过Image组件中ImageType属性中FillAmount,通过代码改变FillAmount的值就可以实现进度条效果 首先在Hierarchy中创建UI>Image,调整ImageType为Filled,FillMethod为Horizontal,拉动 查看详情

如何在unity3d使用www加载场景并显示进度条

参考技术A1.新建两个场景,保存为level1和level22.将图片素材放进工程文件中,分别作为关卡背景、进度条背景和进度条前景3.创建C#脚本,取名Life4.打开脚本,加入如图所示代码5.将脚本拖拽到摄像机上,将三张图片对号入座到图... 查看详情

unity3d场景切换加载进度条实现(代码片段)

需要三个场景,场景A,场景B,场景C;场景A:一个按钮,点击加载场景B;场景B:从A切换到C过度场景,加载进度条;场景C:目标场景;创建OnProgress.cs脚本:usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;usingUnityEngine.Sc... 查看详情

什么是在 Unity3D 制作的游戏中保存游戏进度的最佳实践,以及适用于 Android 和 iOS 的不同版本

】什么是在Unity3D制作的游戏中保存游戏进度的最佳实践,以及适用于Android和iOS的不同版本【英文标题】:WhatisbestPracticetosaveGameProgressinaGamemadeinUnity3DalongdifferentVersionsforAndroidandiOS【发布时间】:2020-07-2500:10:42【问题描述】:为简... 查看详情

ARCore+Unity3D:如何制作面向北方的场景?

】ARCore+Unity3D:如何制作面向北方的场景?【英文标题】:ARCore+Unity3D:Howtomakeasceneorientedtonorth?【发布时间】:2018-03-1801:32:30【问题描述】:我一直在Unity中使用ARCore。我想要实现的是根据输入的GPS坐标和当前GPS位置生成对象(例... 查看详情

unity3d场景导出到3dsmax中使用

Unity3d里的制作的场景整个导出到max里使用可否实现?据我我了解是不能实现的,不知道你为什么要这么做,max是做场景模型的,而unity更加侧重交互的制作,unity制作场景远不如max简单方便,而且unity制作场景,max完全可以实现... 查看详情

[unity3d]unity3d游戏开发之异步记载场景并实现进度条读取效果

...了,所以立即抓紧时间来这里更新博客。博主本来计划在Unity3D游戏开发之从《魂斗罗》游戏说起(上)——目标追踪这篇文章后再写一篇《Unity3D游戏开发之从《魂斗罗》游戏说起(下)》,只是眼下博主的项目进度有些缓慢,所以想... 查看详情

如何在unity3d使用www加载场景并显示进度条

参考技术A异步加载场景,可以使用变量progress查看加载进度5.x:UnityEngine.SceneManagement.SceneManager.LoadSceneAsync("sceneName").progress;4.xApplication.LoadLevelAsync(1).progress;WWW通常使用在访问url时,www.progress可以查看加载进度 查看详情

unity3d-地图制作之光照贴图lightmapping

今天无聊随便翻看了暗黑战神的场景资源,发现了一个以前没怎么注意的静态场景优化问题。 什么是静态场景,也就是说这个场景是不会变化。比如MMO游戏中选择人物的场景。   就拿默认的暗黑战神的选择人物场... 查看详情

unity3d中间获取不在场景中的物体的组件

比方说我要发射一个炮弹,我制作了一个炮弹的预设,我要获取这个炮弹的组件,但是如果在场景中没有这个炮弹的实例,就会显示获取不了组件。如果每次我要实例化一个预设都必须在场景中先实例化一次感觉非常不合理啊。... 查看详情

用unity3d制作一个球体的场景如何做

有个游戏课题是要求用Unity3D制作一个球体的场景,在球体内部贴上贴图制作一个星空的效果,并且在星空上有星星可以拾取的功能。想请问一下如何创建一个球体的场景,并且可以在它内部进行编译。参考技术A找一个星空制作... 查看详情

unity场景制作方式?

我现在在制作游戏场景时,是在unity3D中建一个地形,然后把从3DMax里生成的模型导入到unity3D中,每个模型都要在unity进行调整略显得很麻烦。我想问一下一般专业游戏团队在制作游戏场景时是怎样制作的,是每个模型都要导入进... 查看详情

unity3d——场景制作3d模型

参考技术A利用几个Cube创建一个桌子模型。然后新建一个空物体(Hierarchy->CreateEmpty)命名为Desk,然后将组成桌子的几个Cube一起拖到Desk中。这样Desk就成为了一个整体,对那些Cube一起操作。需要在Assets中分别建立“Materials”和“Te... 查看详情

vue实现loading进度条

项目中遇到的,用vue实现下: 1<template>2<divclass="plLoading">3<divclass="plLoadingContent">4<divclass="plLoadingLogo">5<imgsrc="http://static.crecgec.com/Kaipiao/loadingLogo.png"/ 查看详情