背景

通常游戏的主场景包括的资源较多,这会导致载入场景的时间较长。为了避免这个问题,能够首先载入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动画,然后再载入场景。总之进度条尽管小,但要做好也是不easy的。

參考

  1. 阿高.Unity 显示Loading(载入)进度 对于网上流行的方法进行更正
  2. Unity3d官方论坛.using allowSceneActivation

Unity3d中制作异步Loading进度条所遇到的问题的更多相关文章

  1. unity3d___UGui中如何创建loading...进度条

    http://blog.sina.com.cn/s/blog_e82e8c390102wh2z.html 实现方法:通过Image组件中Image Type属性中Fill Amount,通过代码改变F ...

  2. ASP.NET 给Web中的网页添加Loading进度条形式

    前段时间客户提了一个需求,要求给网站中某些功能添加进度条形式,因为某些功能查询的数据量太大,经常会出现点击Search按钮,但是没有任何反应的情况,会让用户以为网站挂掉了,导致投诉的事情发生,所以客户 ...

  3. 图解CSS3制作圆环形进度条的实例教程

    圆环形进度条制作的基本思想还是画出基本的弧线图形,然后CSS3中我们可以控制其旋转来串联基本图形,制造出部分消失的效果,下面就来带大家学习图解CSS3制作圆环形进度条的实例教程 首先,当有人说你能不能 ...

  4. Android loading进度条使用简单总结

    在这里,总结一下loading进度条的使用简单总结一下. 一.说起进度条,必须说说条形进度条,经常都会使用到嘛,特别是下载文件进度等等,还有像腾讯QQ安装进度条一样,有个进度总给人良好的用户体验. 先 ...

  5. 详解用CSS3制作圆形滚动进度条动画效果

    主  题 今天手把手教大家用CSS3制作圆形滚动进度条动画,想不会都难!那么,到底是什么东东呢?先不急,之前我分享了一个css实现进度条效果的博客<CSS实现进度条和订单进度条>,但是呢, ...

  6. JavaScript之Loading进度条

    一个loading进度条,定义一个fakeProgress方法,定位一个URL,然后setTimeout设置跳转时间我们就能看到我们要打开的URL网址了. 这个链接我就直接链接到我的新浪博客去了,算是 ...

  7. PHP+ajaxForm异步带进度条上传文件实例

    在使用ajaxForm方法之前,首先需要安装form.js的插件,网上有: 一.首先说用法,ajaxForm可以接收0或1个参数,该参数可以是一个变量.一个对象或回调函数,这个对象主要有以下参数: v ...

  8. 模态框的理解 ,jQ: loading,进度条, 省级联动 表单验证 插件

    模态框: 打开一个弹框 不关闭它就不能做框外的操作 必须关闭或弹出另外的弹框 加载延迟loading + 进度条只要有请求 就处理一下监控ajax 全局事件jquery: $('#box').ajax ...

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

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

随机推荐

  1. leetcode-1-basic

    leetcode-algorithm 1. Two Sum 解法:循环,试呗..简单粗暴.. class Solution { public: vector<int> twoSum(vec ...

  2. Oracle联合主键

    转https://www.cnblogs.com/king-xg/p/6721272.html alter table tablename add constraint unionkeyname pr ...

  3. AtCoder Beginner Contest 098 D - Xor Sum 2

    D - Xor Sum 2 Time limit : 2sec / Memory limit : 1024MB Score : 500 points Problem Statement There i ...

  4. Python算法-二叉树深度优先遍历

    二叉树 组成: 1.根节点  BinaryTree:root 2.每一个节点,都有左子节点和右子节点(可以为空)  TreeNode:value.left.right 二叉树的遍历: 遍历二叉树:深度 ...

  5. c++ - 在终端中,cout不显示任何内容

    g++ 是一个编译器,它将源代码转换成可以执行程序,但不运行它. 你必须亲自运行程序. g++ 生成的程序的默认名称是 a.out ( 因为历史原因),因此你将运行它作为 $./a.out   如果要 ...

  6. 【编程工具】Sublime Text3快捷键配置

    我们在使用编译软件时,总是喜欢使用快捷键来方便我们的操作,但有些编译软件不支持快捷键的修改和设置,为了能够更加方便的使用 Sublime Text3,这里我介绍几个 Sublime Text3 设置快 ...

  7. HDU 5483 Nux Walpurgis

    Nux Walpurgis Time Limit: 8000ms Memory Limit: 131072KB This problem will be judged on HDU. Original ...

  8. J2EE 中间件 JVM 集群

    [转]J2EE 中间件 JVM 集群 博客分类: 企业应用面临的问题 Java&Socket 开源组件的应用 jvm应用服务器weblogicjvm集群 1 前言 越来越多的关键任务和大型应用 ...

  9. shell的while循环

    while循环用于不断执行一系列命令,也用于从输入文件中读取数据:命令通常为测试条件.其格式为: while command do    Statement(s) to be executed if ...

  10. 了不得,我可能发现了Jar 包冲突的秘密

    一.前言 这篇是类加载器相关的第三篇: 实战分析Tomcat的类加载器结构(使用Eclipse MAT验证) 还是Tomcat,关于类加载器的趣味实验 昨天下午刚写了篇 类加载器相关的,晚上想着验证个 ...