异步任务相信大家应该不会陌生,那么本章内容MOMO将带领大家学习Unity中的一些异步任务。在同步加载游戏场景的时候通常会使用方法 Application.LoadLevel(“yourScene”); 这句代码执行完毕后程序会干什么呢??如下图所示,这是我随便找了一个游戏场景, 在Hierarchy视图中我们可以看到该场景中“天生”的所有游戏对象。天生的意思就是运行程序前该场景中就已经存在的所有游戏对象。然后这些对象就会在执行完Application.LoadLevel(“yourScene”);方法后加载至内存当中。如果该场景中的游戏对象过多那么瞬间将会出现卡一下的情况,因为LoadLevel()方法是同步进行的。MOMO把这种加载起个名字叫A形式加载。
下面我说说“后天“加载的游戏对象。意思是这些游戏对象是通过脚本动态的创建出来的。比如常用方法 :
|
GameObject Obj=(GameObject)Instantiate(prefab);
|
这句代码执行完毕后同样会在Hierarchy视图中添加对应的游戏对象。MOMO把这种加载起个名字叫B形式加载。
下面我们学习异步加载游戏场景,异步异步顾名思义就是不影响当前游戏场景的前提下加载新场景。通常异步加载的方式分为两种:第一种是异步加载新游戏场景,当新场景加载完成后进入新场景并且销毁之前的场景。第二种:同样异步加载新场景,新场景加载完毕后,保留旧场景的游戏对象并且进入新场景。 这里加载的内容就是上面提到的A形式加载。然后B形式加载不会记入这里的加载。
第一种异步加载游戏场景对应的方法是:
|
Application.LoadLevelAsync("yourScene");
|
第二种异步家在游戏场景对应的方法是:
|
Application.LoadLevelAdditiveAsync("yourScene");
|
这两种方法加载的方式完全一样。异步加载其实重要还是应用于游戏LOADING界面,毕竟LOADING如果采用同步的机制会影响用户体验,说到这里MOMO告诉大家如何在Unity中制作游戏进度条。我们应当在Unity中创建一个专门用于读取进度的场景,假设A场景到C场景,我们应当让A场景先到读取进度的场景B场景,当异步任务完成后在进入C场景。 A – 》B -》 C ,在B场景中绘制游戏进度条或读取动画。因为B场景仅仅是个显示LOADING动画的场景,所以读取该场景是瞬间就完成的。
程序在切换场景时应当有一个全全局的静态变量来记录简要读取的场景名称。这里简单的写一下。
|
usingUnityEngine;
usingSystem.Collections;
publicclassGlobe
{
//在这里记录当前切换场景的名称
publicstaticstringloadName;
}
|
在A场景中通过某些触发条件 调用LoadLevel进入B场景。
|
//记录LOADING场景中需要读取的C场景名称
Globe.loadName="C";
//先进入B场景
Application.LoadLevel("B");
|
OK我们在B场景中异步读取C场景与 播放读取动画,Loading.cs 绑定在B场景的摄像机对象身上。当C场景异步读取完毕后即可直接进入C场景。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
usingUnityEngine;
usingSystem.Collections;
publicclassLoading:MonoBehaviour{
privatefloatfps=10.0f;
privatefloattime;
//一组动画的贴图,在编辑器中赋值。
publicTexture2D[]animations;
privateintnowFram;
//异步对象
AsyncOperation async;
//读取场景的进度,它的取值范围在0 - 1 之间。
intprogress=0;
voidStart()
{
//在这里开启一个异步任务,
//进入loadScene方法。
StartCoroutine(loadScene());
}
//注意这里返回值一定是 IEnumerator
IEnumerator loadScene()
{
//异步读取场景。
//Globe.loadName 就是A场景中需要读取的C场景名称。
async=Application.LoadLevelAsync(Globe.loadName);
//读取完毕后返回, 系统会自动进入C场景
yield returnasync;
}
voidOnGUI()
{
//因为在异步读取场景,
//所以这里我们可以刷新UI
DrawAnimation(animations);
}
voidUpdate()
{
//在这里计算读取的进度,
//progress 的取值范围在0.1 - 1之间, 但是它不会等于1
//也就是说progress可能是0.9的时候就直接进入新场景了
//所以在写进度条的时候需要注意一下。
//为了计算百分比 所以直接乘以100即可
progress= (int)(async.progress*100);
//有了读取进度的数值,大家可以自行制作进度条啦。
Debug.Log("xuanyusong"+progress);
}
//这是一个简单绘制2D动画的方法,没什么好说的。
void DrawAnimation(Texture2D[]tex)
{
time+=Time.deltaTime;
if(time>=1.0/fps){
nowFram++;
time=0;
if(nowFram>=tex.Length)
{
nowFram=0;
}
}
GUI.DrawTexture(newRect(100,100,40,60),tex[nowFram]);
//在这里显示读取的进度。
GUI.Label(newRect(100,180,300,60),"lOADING!!!!!"+progress);
}
}
|
OK 下面我们继续学习在游戏场景中加载对象,文章的开始MOMO已经告诉大家,游戏场景中Hierarchy视图中的所有的对象在切换场景的时候都会加载。其实有一种方法可以让某些游戏对象不会被加载,如下图所示,首先在Hierarchy视图中选择一个游戏对象,在右侧监测面板视图中我们可以看到一个 “小对勾”默认情况下是勾选状态,说明该游戏对象处于激活状态,如果点掉的话该对象将被隐藏。这个小功能在开发中其实用处非常大,请大家务必记住哈。
此时此刻大家相像一个游戏场景,默认进入的时候是没有任何游戏对象的,然后运行游戏时开启一个异步任务将它们一个一个的加载显示出来,这种方式适合异步的加载一个比较大的游戏场景。
Test.cs 把它挂在摄像机对象中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
usingUnityEngine;
usingSystem.Collections;
publicclassTest:MonoBehaviour{
//这里是需要加载激活的游戏对象
publicGameObject []Objects;
//当前加载的进度
intload_index=0;
voidStart()
{
//开启一个异步任务,加载模型。
StartCoroutine(loadObject());
}
IEnumerator loadObject()
{
//便利所有游戏对象
foreach(GameObject obj inObjects)
{
//激活游戏对象
obj.active=true;
//记录当前加载的对象
load_index++;
//这里可以理解为通知主线程刷新UI
yield return0;
}
//全部便利完毕返回
yield return0;
}
voidOnGUI()
{
//显示加载的进度
GUILayout.Box("当前加载的对象ID是: "+load_index);
}
}
|
如下图所示,我们把需要加载的游戏对象以数组的形式放在Objects数组中,因为这些对象属于未激活状态,所以不能通过Find 等方法在脚步那种中找到他们。讲到这里我们在说说 编辑器赋值与代码中赋值的区别,编辑器中赋值所消耗的时间都会记在loadlevel ()读取场景中。而代码中使用Resource.load()这类方法所消耗的时间会记在脚本中。开发中还得自行的把握一下把loading加在那里。
当然我们还可以使用Instantiate(prefab);方法来动态的创建游戏对象。
Main.cs 把它挂在摄像机中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
usingUnityEngine;
usingSystem.Collections;
publicclassMain:MonoBehaviour
{
publicintcount;
//在编辑器中预设一个游戏对象
public GameObject prefab;
voidStart()
{
StartCoroutine(loaditem());
}
voidOnGUI()
{
GUILayout.Box("游戏对象已经加载到 : "+count);
}
IEnumerator loaditem()
{
//开始加载游戏对象
for(inti=0;i<1000;i++)
{
Instantiate(prefab);
count=i;
//可以理解为刷新UI,显示新加载的游戏对象
yield return0;
}
//结束
yield return0;
}
}
|
运行游戏后该游戏对象会循环1000遍逐个创建,不影响主线程。那么今天我们其实学习最多的就是StartCoroutine(),其实就是开启一个异步线程,这里可能有朋友会问Thread可以代替它吗? 答案是不行, 比如查询数据库的时候如果用Thread的话Unity就会报错说不能在线程中查询,但是在StartCoroutine()中就可以完成,所以开发中大家可以尝试着使用它,我们还可以使用StopCoroutine(“name”)来关闭一个正在执行的异步线程。
分享到:
相关推荐
Unity3D之异步加载游戏场景中关于进度条显示
这个是一款 Unity3D异步加载场景资源 ,界面简洁漂亮的加载画面,内含多个样式,提供给广大的Unity3D学者研究。
。
。
当项目js(css)文件使用越来越多,js 文件的加载也成了性能上的一个问题,此资源能够在页面全部加载完成后异步加载js等资源文件,它可以顺序加载资源列表,也可以并发加载资源列表,它包含一个方法调用接口:...
unity实现场景异步加载并带有加载的进度条,实现场景平稳加载,返回的加载进度为匀速加载。非常适合用在要加载大型场景的情况下。
避免了跳转场景时界面卡住不动的尴尬,使用时只需把scene0放入游戏的第一个场景即可,跳转场景时直接调用ChangeSceneManager.Instance.ChangeScene()方法即可进入动态加载场景界面,无需再创建跳转场景的UI。...
Unity3D异步加载场景
实现了u3d异步加载场景时跳转界面的进度条平滑加载,并且有加载特效,需要有一定基础才能看懂
WPF的ItemsControl的ItemsSource的异步加载,引用程序集,使用依赖项属性,可以异步加载。
WPF制作的DataGrid异步加载程序,使用MVVM设计模式
Android AsyncTask用法和异步加载图片通过AsyncTask 从网络上异步加载一张图片
图片异步加载,照片墙,异步加载listview中的图片 代码3 说明:http://blog.csdn.net/wjyyxzzjnws/article/details/10041125
2、LoadSceneManager.Instance.LoadSceneAsync 即可异步加载场景; 3、LoadSceneManager.Instance.LoadScene 即可同步加载场景; 4、LoadSceneManager.Instance.ProgressLoadSceneAsync 即可获取异步加载进度;
基于Unity封装的AB包资源管理器,实现同步加载/异步加载AB包以及依赖包,详细可以到我的博客查看文章,里面也有完整代码。
异步加载 仿expandListView效果 分页异步加载 仿expandListView效果 分页异步加载 仿expandListView效果 分页异步加载 仿expandListView效果 分页
winform的一个简单易用异步加载等待效果,调用方式: this.AsyncWaitDo(delegate{ //异步等待操作}, delegate{//回调操作}); this是要进行异步等待的窗体
异步加载,主线程,子线程的关系
Android 图片异步加载 加载网络图片
异步加载全攻略,包括:thread加载、asyncTask加载、lruCache等