`

Unity3d中制作Loading场景进度条所遇到的问题

阅读更多
http://www.58player.com/blog-2537-89690.html
  背景
         通常游戏的主场景包含的资源较多,这会导致加载场景的时间较长。为了避免这个问题,可以首先加载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() {
            AsyncOperation op = Application.LoadLevelAsync(1);
            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一直为false,AsyncOperation.progress的值增加到0.9后就保持不变了,也就是说场景永远不会被加载完毕。
         
         在这个帖子中找到了答案,原来把allowSceneActivation设置为false后,Unity就只会加载场景到90%,剩下的10%要等到allowSceneActivation设置为true后才加载,这不得不说是一个坑。所以代码改为如下。当AsyncOperation.progress到达0.9后,就直接把进度条的数值更新为100%,然后设置AsyncOperation.allowSceneActivation为ture,让Unity继续加载未完成的场景。
        
         private IEnumerator StartLoading_3() {
            AsyncOperation op = Application.LoadLevelAsync(1);
            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 displayProgress = 0;
            int toProgress = 0;
            AsyncOperation op = Application.LoadLevelAsync(1);
            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动画,然后再加载场景。总之进度条虽然小,但要做好也是不容易的。
分享到:
评论

相关推荐

    Unity3D之异步加载与进度条

    下面我们将详细介绍 Unity3D 中的异步加载与进度条的实现。 异步加载 异步加载是一种非阻塞式的加载方式,能够在不影响当前游戏场景的情况下加载新场景。Unity3D 中提供了两种异步加载的方法:Application....

    Unity3D之进度条插件Loading Component

    **Loading Component**是一款专为Unity3D设计的进度条插件,它可以帮助开发者快速实现游戏中的加载界面或进度显示功能。通过这个插件,你可以轻松自定义加载界面的样式、动画效果以及加载逻辑等,极大地提升了开发...

    unity游戏场景资源加载进度条Loading Screens for Mad Level Manager

    unity游戏场景资源加载进度条Loading Screens for Mad Level Manager ,5种预制进度条样式,自动计算加载时间,支持uGUI和NGUI,可定制强,并且有个等待中与玩家互动的功能,大家自己研究下。

    Unity3D多个异步加载场景资源 简洁漂亮的加载画面

    在Unity3D游戏开发中,异步加载(Asynchronous Loading)是提高用户体验的关键技术之一,尤其是在处理大型场景或大量资源时。本项目提供了一个简洁且漂亮的加载画面,旨在帮助Unity3D学者理解和实现游戏资源的高效...

    Unity3D游戏开发之异步加载游戏场景与异步加载游戏资源进度条.pdf

    本章主要讲解Unity3D中如何实现游戏场景和资源的异步加载,以及如何创建游戏进度条。 首先,我们来看同步加载。在Unity中,使用`Application.LoadLevel("yourScene")`方法可以同步加载指定场景。这个过程是阻塞的,...

    Unity3D的进度条显示当前加载的百分比2

    本篇将深入探讨如何在Unity3D中实现进度条来显示当前加载的百分比。 Unity3D提供了`Application.LoadLevelAsync`方法,用于异步加载场景,这正是实现进度条的关键。`LoadLevelAsync`方法允许游戏在加载新场景的同时...

    unity loading过渡

    在Unity 3D游戏开发过程中,场景之间的过渡是非常重要的一个环节,良好的过渡不仅可以提升玩家的游戏体验,还能有效管理游戏资源的加载与卸载,从而提高游戏性能。本文将详细介绍两种常见的Unity场景过渡方法及其...

    异步加载进度条案例素材.zip

    "异步加载进度条案例素材.zip" 包含了一个名为 "Loading Screen.unitypackage" 的资源包,这个包里可能包含了实现异步加载进度条的示例场景、脚本和其他相关素材。 首先,理解Unity中的异步加载机制。Unity使用`...

    Unity可自定义loading页的异步加载工具,免费下载,使用说明

    "unity-ZTools-LoadSceneAsync"是本压缩包中的核心文件,这很可能是一个Unity工程的插件或者脚本集合,包含了实现异步加载和自定义加载页面所需的功能。在使用这个工具时,开发者可能需要将这些文件导入到自己的...

    unity-带输入跳转的分页加载组件

    UGUI是Unity引擎提供的基于图标的用户界面系统,用于创建2D和3D游戏中的各种交互元素。 该组件的实现可能包括以下几个关键部分: 1. **页控制器(Page Controller)**:管理当前显示的页面,以及用户的翻页请求。...

    UnityWebGL_StageRun

    Unity WebGL 是Unity游戏引擎的一个重要特性,它允许开发者将3D和2D游戏直接发布到Web平台,无需用户下载安装额外的应用程序。"UnityWebGL_StageRun"可能是一个使用Unity WebGL技术创建的游戏或者交互式内容的项目。...

    加载中下落特效

    实现加载中下落特效的技术手段多样,可以使用HTML、CSS和JavaScript进行前端开发,也可以利用Unity3D、Cocos2d-x等游戏引擎来创建更复杂的3D效果。在HTML5中,我们可以利用Canvas元素配合JavaScript实现自定义的动画...

Global site tag (gtag.js) - Google Analytics