Unity3d中制作异步Loading进度条所遇到的问题
背景
通常游戏的主场景包括的资源较多,这会导致载入场景的时间较长。为了避免这个问题,能够首先载入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一直为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(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动画,然后再载入场景。总之进度条尽管小,但要做好也是不easy的。
參考
- 阿高.Unity 显示Loading(载入)进度 对于网上流行的方法进行更正
- Unity3d官方论坛.using allowSceneActivation
Unity3d中制作异步Loading进度条所遇到的问题的更多相关文章
- unity3d___UGui中如何创建loading...进度条
http://blog.sina.com.cn/s/blog_e82e8c390102wh2z.html 实现方法:通过Image组件中Image Type属性中Fill Amount,通过代码改变F ...
- ASP.NET 给Web中的网页添加Loading进度条形式
前段时间客户提了一个需求,要求给网站中某些功能添加进度条形式,因为某些功能查询的数据量太大,经常会出现点击Search按钮,但是没有任何反应的情况,会让用户以为网站挂掉了,导致投诉的事情发生,所以客户 ...
- 图解CSS3制作圆环形进度条的实例教程
圆环形进度条制作的基本思想还是画出基本的弧线图形,然后CSS3中我们可以控制其旋转来串联基本图形,制造出部分消失的效果,下面就来带大家学习图解CSS3制作圆环形进度条的实例教程 首先,当有人说你能不能 ...
- Android loading进度条使用简单总结
在这里,总结一下loading进度条的使用简单总结一下. 一.说起进度条,必须说说条形进度条,经常都会使用到嘛,特别是下载文件进度等等,还有像腾讯QQ安装进度条一样,有个进度总给人良好的用户体验. 先 ...
- 详解用CSS3制作圆形滚动进度条动画效果
主 题 今天手把手教大家用CSS3制作圆形滚动进度条动画,想不会都难!那么,到底是什么东东呢?先不急,之前我分享了一个css实现进度条效果的博客<CSS实现进度条和订单进度条>,但是呢, ...
- JavaScript之Loading进度条
一个loading进度条,定义一个fakeProgress方法,定位一个URL,然后setTimeout设置跳转时间我们就能看到我们要打开的URL网址了. 这个链接我就直接链接到我的新浪博客去了,算是 ...
- PHP+ajaxForm异步带进度条上传文件实例
在使用ajaxForm方法之前,首先需要安装form.js的插件,网上有: 一.首先说用法,ajaxForm可以接收0或1个参数,该参数可以是一个变量.一个对象或回调函数,这个对象主要有以下参数: v ...
- 模态框的理解 ,jQ: loading,进度条, 省级联动 表单验证 插件
模态框: 打开一个弹框 不关闭它就不能做框外的操作 必须关闭或弹出另外的弹框 加载延迟loading + 进度条只要有请求 就处理一下监控ajax 全局事件jquery: $('#box').ajax ...
- 【转】Unity3d中制作Loading场景进度条所遇到的问题 LoadLevelAsync,AsyncOperation
背景 通常游戏的主场景包含的资源较多,这会导致加载场景的时间较长.为了避免这个问题,可以首先加载Loading场景,然后再通过Loading场景来加载主场景.因为Loading场景包含的资源较少,所以 ...
随机推荐
- PAT Basic 1072
1072 开学寄语 下图是上海某校的新学期开学寄语:天将降大任于斯人也,必先删其微博,卸其 QQ,封其电脑,夺其手机,收其 ipad,断其 wifi,使其百无聊赖,然后,净面.理发.整衣,然后思过.读 ...
- Linux文件管理类命令及命令别名
文件查看类命令: cat: tac: 从文件尾部开始显示 分屏显示: more [option] 文件名: 查看至文件尾部会退出 空格为翻页 less [option] 文件名: 查看至文件尾部不退出 ...
- 通过 PC 远程控制 Android 的应用 -- 可以将手机屏幕投射显示到电脑上
测试结果中的部分测试图:Mobizen手机界面: 电脑界面: 主界面 视频 全屏视频 WebKey手机界面: 电脑界面: AirMore手机界面: 电脑界面:主界面 镜像 全屏镜像 Airdroid手 ...
- 虚拟机里linux系统安装 CentOS 64-bit(6.4版本)——笔记
使用的虚拟机是VMware WorkStation 9.0(9.0.0 build-812388) 1. 安装过程中 选择 桥接 此系统可以拥有独立ip.Nat模式跟主机ip一样 2. 安装过程中选择 ...
- 4,list,list的列表嵌套,range
list 索引,切片+步长 # li = [, True, (, , , , , , '小明',], {'name':'alex'}] #索引,切片,步长 # print(li[]) # print( ...
- BNUOJ 6727 Bone Collector
Bone Collector Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on HDU. Origin ...
- Leetcode 391.完美矩形
完美矩形 我们有 N 个与坐标轴对齐的矩形, 其中 N > 0, 判断它们是否能精确地覆盖一个矩形区域. 每个矩形用左下角的点和右上角的点的坐标来表示.例如, 一个单位正方形可以表示为 [1,1 ...
- 九度oj 题目1367:二叉搜索树的后序遍历序列
题目描述: 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则输出Yes,否则输出No.假设输入的数组的任意两个数字都互不相同. 输入: 每个测试案例包括2行: 第一行为1个整数 ...
- RabbitMQ的transaction、confirm、ack三个概念的解释
在使用RabbitMQ的过程中,肯定会遇到这样的几个概念:transaction.confirm.ack.本文介绍一下这几个概念,以及他们之间的关系. RabbitMQ是采用的AMQP协议,AMQP协 ...
- iOS代理转移
在控制器里面想调用一个视图的子视图的代理方法很简单 1.找到子视图的协议和代理属性 2.给你想调用的控件添加代理属性,遵守的协议和子视图的一样 3.重写代理属性的set方法