当前位置: 首页 > news >正文

Unity3D - 异步加载游戏场景与异步加载游戏资源进度条 ...

异步任务相信大家应该不会陌生,那么本章内容MOMO将带领大家学习Unity中的一些异步任务。在同步加载游戏场景的时候通常会使用方法 Application.LoadLevel(“yourScene”); 这句代码执行完毕后程序会干什么呢??如下图所示,这是我随便找了一个游戏场景, 在Hierarchy视图中我们可以看到该场景中“天生”的所有游戏对象。天生的意思就是运行程序前该场景中就已经存在的所有游戏对象。然后这些对象就会在执行完Application.LoadLevel(“yourScene”);方法后加载至内存当中。如果该场景中的游戏对象过多那么瞬间将会出现卡一下的情况,因为LoadLevel()方法是同步进行的。我们把这种加载起个名字叫A形式加载。

下面我说说“后天“加载的游戏对象。意思是这些游戏对象是通过脚本动态的创建出来的。比如常用方法 :

1 GameObject Obj = (GameObject)Instantiate(prefab);

这句代码执行完毕后同样会在Hierarchy视图中添加对应的游戏对象。我们把这种加载起个名字叫B形式加载。

下面我们学习异步加载游戏场景,异步异步顾名思义就是不影响当前游戏场景的前提下加载新场景。通常异步加载的方式分为两种:第一种是异步加载新游戏场景,当新场景加载完成后进入新场景并且销毁之前的场景。第二种:同样异步加载新场景,新场景加载完毕后,保留旧场景的游戏对象并且进入新场景。 这里加载的内容就是上面提到的A形式加载。然后B形式加载不会记入这里的加载。

第一种异步加载游戏场景对应的方法是:

1 Application.LoadLevelAsync("yourScene");

第二种异步家在游戏场景对应的方法是:

1 Application.LoadLevelAdditiveAsync ("yourScene");
这两种方法加载的方式完全一样。异步加载其实重要还是应用于游戏LOADING界面,毕竟LOADING如果采用同步的机制会影响用户体验,说到这里MOMO告诉大家如何在Unity中制作游戏进度条。我们应当在Unity中创建一个专门用于读取进度的场景,假设A场景到C场景,我们应当让A场景先到读取进度的场景B场景,当异步任务完成后在进入C场景。 A – 》B -》 C ,在B场景中绘制游戏进度条或读取动画。因为B场景仅仅是个显示LOADING动画的场景,所以读取该场景是瞬间就完成的。

程序在切换场景时应当有一个全全局的静态变量来记录简要读取的场景名称。这里简单的写一下。

1 using UnityEngine;
2 using System.Collections;
3
4 public class Globe
5 {
6 //在这里记录当前切换场景的名称
7 public static string loadName;
8 }

在A场景中通过某些触发条件 调用LoadLevel进入B场景。

1 //记录LOADING场景中需要读取的C场景名称
2 Globe.loadName = "C";
3 //先进入B场景
4 Application.LoadLevel ("B");

OK我们在B场景中异步读取C场景与 播放读取动画,Loading.cs 绑定在B场景的摄像机对象身上。当C场景异步读取完毕后即可直接进入C场景。

01 using UnityEngine;
02 using System.Collections;
03
04 public class Loading : MonoBehaviour {
05
06 private float fps = 10.0f;
07 private float time;
08 //一组动画的贴图,在编辑器中赋值。
09 public Texture2D[] animations;
10 private int nowFram;
11 //异步对象
12 AsyncOperation async;
13
14 //读取场景的进度,它的取值范围在0 - 1 之间。
15 int progress = 0;
16
17 void Start()
18 {
19 //在这里开启一个异步任务,
20 //进入loadScene方法。
21 StartCoroutine(loadScene());
22 }
23
24 //注意这里返回值一定是 IEnumerator
25 IEnumerator loadScene()
26 {
27 //异步读取场景。
28 //Globe.loadName 就是A场景中需要读取的C场景名称。
29 async = Application.LoadLevelAsync(Globe.loadName);
30
31 //读取完毕后返回, 系统会自动进入C场景
32 yield return async;
33
34 }
35
36 void OnGUI()
37 {
38 //因为在异步读取场景,
39 //所以这里我们可以刷新UI
40 DrawAnimation(animations);
41
42 }
43
44 void Update()
45 {
46
47 //在这里计算读取的进度,
48 //progress 的取值范围在0.1 - 1之间, 但是它不会等于1
49 //也就是说progress可能是0.9的时候就直接进入新场景了
50 //所以在写进度条的时候需要注意一下。
51 //为了计算百分比 所以直接乘以100即可
52 progress = (int)(async.progress *100);
53
54 //有了读取进度的数值,大家可以自行制作进度条啦。
55 Debug.Log("xuanyusong" +progress);
56
57 }
58 //这是一个简单绘制2D动画的方法,没什么好说的。
59 void DrawAnimation(Texture2D[] tex)
60 {
61
62 time += Time.deltaTime;
63
64 if(time >= 1.0 / fps){
65
66 nowFram++;
67
68 time = 0;
69
70 if(nowFram >= tex.Length)
71 {
72 nowFram = 0;
73 }
74 }
75 GUI.DrawTexture(new Rect( 100,100,40,60) ,tex[nowFram] );
76
77 //在这里显示读取的进度。
78 GUI.Label(new Rect( 100,180,300,60), "lOADING!!!!!" + progress);
79
80 }
81
82 }

OK 下面我们继续学习在游戏场景中加载对象,文章的开始已经告诉大家,游戏场景中Hierarchy视图中的所有的对象在切换场景的时候都会加载。其实有一种方法可以让某些游戏对象不会被加载,如下图所示,首先在Hierarchy视图中选择一个游戏对象,在右侧监测面板视图中我们可以看到一个 “小对勾”默认情况下是勾选状态,说明该游戏对象处于激活状态,如果点掉的话该对象将被隐藏。这个小功能在开发中其实用处非常大,请大家务必记住哈。

此时此刻大家相像一个游戏场景,默认进入的时候是没有任何游戏对象的,然后运行游戏时开启一个异步任务将它们一个一个的加载显示出来,这种方式适合异步的加载一个比较大的游戏场景。

Test.cs 把它挂在摄像机对象中。

01 using UnityEngine;
02 using System.Collections;
03
04 public class Test : MonoBehaviour {
05
06 //这里是需要加载激活的游戏对象
07 public GameObject [] Objects;
08
09 //当前加载的进度
10 int load_index =0;
11 void Start ()
12 {
13 //开启一个异步任务,加载模型。
14 StartCoroutine(loadObject());
15 }
16
17 IEnumerator loadObject()
18 {
19 //便利所有游戏对象
20 foreach(GameObject obj in Objects)
21 {
22 //激活游戏对象
23 obj.active = true;
24 //记录当前加载的对象
25 load_index ++;
26
27 //这里可以理解为通知主线程刷新UI
28 yield return 0;
29 }
30 //全部便利完毕返回
31 yield return 0;
32 }
33
34 void OnGUI ()
35 {
36 //显示加载的进度
37 GUILayout.Box("当前加载的对象ID是: " + load_index);
38 }
39 }

相关文章:

  • 基于时间轮的定时器
  • PostgreSQL 快速给指定表每个字段创建索引 - 1
  • 前后端分离,tomcat特殊字符不识别问题
  • 纯前端的分页(利用vant的List组件)
  • 汉诺塔问题(Hanoi Tower)递归算法解析(Python实现)
  • 数据库(MySQL)
  • Hive分桶
  • 第三章:内存分配与回收策略
  • visual studio 命令行 build
  • 摘要商城总结
  • StringBuufer与StringBulder线程的区别
  • 微信分享到朋友圈,怎么自定义分享的标题,图片,内容?
  • BZOJ2300[HAOI2011]防线修建——非旋转treap+凸包(平衡树动态维护凸包)
  • 今日学习20190425
  • MAYA 卸载工具,完美彻底卸载清除干净maya各种残留注册表和文件
  • php的引用
  • 【Leetcode】101. 对称二叉树
  • 【402天】跃迁之路——程序员高效学习方法论探索系列(实验阶段159-2018.03.14)...
  • canvas绘制圆角头像
  • Cookie 在前端中的实践
  • ESLint简单操作
  • Facebook AccountKit 接入的坑点
  • Git的一些常用操作
  • HTTP请求重发
  • Javascript 原型链
  • nodejs调试方法
  • React-flux杂记
  • RxJS 实现摩斯密码(Morse) 【内附脑图】
  • Sass 快速入门教程
  • scrapy学习之路4(itemloder的使用)
  • sessionStorage和localStorage
  • ubuntu 下nginx安装 并支持https协议
  • vue 配置sass、scss全局变量
  • vue从创建到完整的饿了么(18)购物车详细信息的展示与删除
  • Web Storage相关
  • Yeoman_Bower_Grunt
  • 服务器之间,相同帐号,实现免密钥登录
  • 爬虫模拟登陆 SegmentFault
  • 深度解析利用ES6进行Promise封装总结
  • 使用 Node.js 的 nodemailer 模块发送邮件(支持 QQ、163 等、支持附件)
  • 微龛半导体获数千万Pre-A轮融资,投资方为国中创投 ...
  • ### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTr
  • #define与typedef区别
  • (C#)获取字符编码的类
  • (C语言)球球大作战
  • (react踩过的坑)antd 如何同时获取一个select 的value和 label值
  • (二)Linux——Linux常用指令
  • (附源码)spring boot基于Java的电影院售票与管理系统毕业设计 011449
  • (十)T检验-第一部分
  • (四)图像的%2线性拉伸
  • (完整代码)R语言中利用SVM-RFE机器学习算法筛选关键因子
  • (译) 函数式 JS #1:简介
  • ... 是什么 ?... 有什么用处?
  • .net core 6 集成 elasticsearch 并 使用分词器
  • .NET Core实战项目之CMS 第十二章 开发篇-Dapper封装CURD及仓储代码生成器实现