NGUI 现有的进度条存在的问题:

进度条跳跃式前进,加载到90%后卡住,突然进入下一个场景。接下来就是解决这个问题。

背景

通常游戏的主场景包含的资源较多,这会导致加载场景的时间较长。为了避免这个问题,可以首先加载Loading场景,然后再通过Loading场景来加载主场景。因为Loading场景包含的资源较少,所以加载速度快。在加载主场景的时候一般会在Loading界面中显示一个进度条来告知玩家当前加载的进度。在Unity中可以通过调用Application.LoadLevelAsync函数来异步加载游戏场景,通过查询AsyncOperation.progress的值来得到场景加载的进度。 
         尝试——遇到问题 
         第一步当加载完Loading场景后,调用如下的LoadGame函数开始加载游戏场景,使用异步加载的方式加载场景1(Loading场景为0,主场景为1),通过Unity提供的Coroutine机制,我们可以方便的在每一帧结束后调用SetLoadingPercentage函数来更新界面中显示的进度条的数值。

 public void LoadGame() {
StartCoroutine(StartLoading_1());
} private IEnumerator StartLoading_1(int scene) {
AsyncOperation op = Application.LoadLevelAsync(scene);
while(!op.isDone) {
SetLoadingPercentage(op.progress * );
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();
op.allowSceneActivation = false;
while(!op.isDone) {
SetLoadingPercentage(op.progress * );
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();
op.allowSceneActivation = false;
while(op.progress < 0.9f) {
SetLoadingPercentage(op.progress * );
yield return new WaitForEndOfFrame();
}
SetLoadingPercentage();
yield return new WaitForEndOfFrame();
op.allowSceneActivation = true;
}

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

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

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

(转)Unity3D游戏开发 NGUI之渐变加载到100%的Loading场景进度条的更多相关文章

  1. 【转】Unity3d中制作Loading场景进度条所遇到的问题 LoadLevelAsync,AsyncOperation

    背景 通常游戏的主场景包含的资源较多,这会导致加载场景的时间较长.为了避免这个问题,可以首先加载Loading场景,然后再通过Loading场景来加载主场景.因为Loading场景包含的资源较少,所以 ...

  2. Unity3D中制作Loading场景进度条

    背景 通常游戏的主场景包含的资源较多,这会导致加载场景的时间较长.为了避免这个问题,可以首先加载Loading场景,然后再通过Loading场景来加载主场景.由于Loading场景包含的资源较少,所以 ...

  3. [Unity3D]Unity3D游戏开发之跑酷游戏项目解说

    大家好,我是秦元培.我參加了CSDN2014博客之星的评选,欢迎大家为我投票,同一时候希望在新的一年里大家能继续支持我的博客. 大家晚上好.我是秦元培,欢迎大家关注我的博客,我的博客地址是blog.c ...

  4. Unity3D游戏开发初探—2.初步了解3D模型基础

    一.什么是3D模型? 1.1 3D模型概述 简而言之,3D模型就是三维的.立体的模型,D是英文Dimensions的缩写. 3D模型也可以说是用3Ds MAX建造的立体模型,包括各种建筑.人物.植被. ...

  5. 从一点儿不会开始——Unity3D游戏开发学习(一)

    一些废话 我是一个windows phone.windows 8的忠实粉丝,也是一个开发者,开发数个windows phone应用和两个windows 8应用.对开发游戏一直抱有强烈兴趣和愿望,但奈何 ...

  6. Unity3D游戏开发之连续滚动背景

    Unity3D游戏开发之连续滚动背景 原文  http://blog.csdn.net/qinyuanpei/article/details/22983421 在诸如天天跑酷等2D游戏中,因为游戏须要 ...

  7. Unity3D游戏开发从零单排(四) - 制作一个iOS游戏

    提要 此篇是一个国外教程的翻译,尽管有点老,可是适合新手入门. 自己去写代码.debug,布置场景,能够收获到非常多.游戏邦上已经有前面两部分的译文,这里翻译的是游戏的最后一个部分. 欢迎回来 在第一 ...

  8. [Unity3D]Unity3D游戏开发之飞机大战项目解说

    大家好,我是秦元培,欢迎大家继续关注我的博客,我的博客地址是blog.csdn.net/qinyuanpei. 首先感谢大家对我博客的关注,今天我想和大家分享的是一个飞机大战的项目.这是一个比較综合的 ...

  9. [Unity3D]Unity3D游戏开发《反对》说到游戏(上)——目标跟踪

    朋友,大家好.我是秦培,欢迎关注我的博客.我的博客地址blog.csdn.net/qinyuanpei. 首先博主要自我反省,过了这么久才来更新博客,这段时间主要是在忙着写期末的作业,所以博主基本上没 ...

随机推荐

  1. rem是如何实现自适应中的?

    使用rem 然后根据媒体查询实现自适应.跟使用JS来自适应也是同个道理,不过是js更精确一点.使用媒体查询: html { font-size: 62.5% } @media only screen ...

  2. PHP 按二维数组的键值排序

    /** * 按二维数组的键值排序 * @param unknown $array 二维数组 * @param unknown $key 二维数组的键值 * @param string $order 升 ...

  3. 设计模式-工厂方法模式(FactoryMethod)

    简介: 简单工厂模式将类的示例化放在工厂对象中. 工厂方法模式是简单工厂模式的延伸,不同的是其将子类的实例化延迟到子类工厂中实现,本身仅定义一个创建对象的接口. 工厂方法模式主要由四部分组成: 1.抽 ...

  4. Lwip的相关资料

    文件资料 Lwip编程指南 Lwip协议栈的设计与实现 分析Lwip

  5. Apache实现Web Server负载均衡

    修改服务器A上apache的http.conf文件: 首先,加载相应的代理模块,去掉以下模块前面的#号: LoadModule proxy_module modules/mod_proxy.soLoa ...

  6. 使用nodejs引用socket.io做聊天室

    Server: var app = require('http').createServer(handler) , io = require('socket.io').listen(app) , fs ...

  7. Eruda——手机网页前端调试面板

    前言 进行移动端网页开发时,想要查看手机浏览器信息从来都不是一件容易的事.特别是当目标环境为APP内置WebView,需要调用特定的JsBridge接口时,你根本都干不了什么,只能一遍又一遍地修改代码 ...

  8. 为php安装memcached扩展连接memcached服务器

    首先必须完成必要的软件安装,memcached是php连接memcached服务器的php扩展 以前有个叫memcache也是php连接memcached服务器的扩展 php的memcache和mem ...

  9. mac brew install redis

    在mac 下安装redis 执行brew install redis ==> Downloading http://download.redis.io/releases/redis-2.8.19 ...

  10. 转:浅谈关于b、h标签的优化技巧

    <b>标签优化 <b>标签是一种加粗标记,作用就是加粗文章中的关键词,对于文章中重要的关键词加粗起到有利于用户阅读的作用.<b>标签的使用对于优化的作用是非常大的, ...