[Unity3D]异步加载游戏场景与异步加载游戏资源进度条

摘要: 异步任务相信大家应该不会陌生,那么本章内容MOMO将带领大家学习Unity中的一些异步任务。在同步加载游戏场景的时候通常会使用方法 Application.LoadLevel(“yourScene”); 这句代码执行完毕后程序会干什么呢??如下 ...


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

 

 

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

[代码]

GameObject Obj = (GameObject)Instantiate(prefab);

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

 

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

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

[代码]:

Application.LoadLevelAsync("yourScene");

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

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

[代码]:

using UnityEngine;
using System.Collections;

public class Globe
{
         //在这里记录当前切换场景的名称
	 public static string loadName;
}

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

[代码]:

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

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

[代码]:

using UnityEngine;
using System.Collections;

public class Loading : MonoBehaviour {

	private float fps = 10.0f;
	private float time;
	//一组动画的贴图,在编辑器中赋值。
	public Texture2D[] animations;
	private int nowFram;
	//异步对象
	AsyncOperation async;

	//读取场景的进度,它的取值范围在0 - 1 之间。
	int progress = 0;

	void Start()
	{
		//在这里开启一个异步任务,
		//进入loadScene方法。
	  	StartCoroutine(loadScene());
	}

	//注意这里返回值一定是 IEnumerator
	IEnumerator loadScene()
	{
		//异步读取场景。
		//Globe.loadName 就是A场景中需要读取的C场景名称。
		async = Application.LoadLevelAsync(Globe.loadName);

		//读取完毕后返回, 系统会自动进入C场景
		yield return async;

	}

	void OnGUI()
	{
		//因为在异步读取场景,
		//所以这里我们可以刷新UI
		DrawAnimation(animations);

	}

	void Update()
	{

		//在这里计算读取的进度,
		//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(new Rect( 100,100,40,60) ,tex[nowFram] );

        //在这里显示读取的进度。
		GUI.Label(new Rect( 100,180,300,60), "lOADING!!!!!" + progress);

	}

}

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

 

 

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

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

[代码]:

using UnityEngine;
using System.Collections;

public class Test : MonoBehaviour {

	//这里是需要加载激活的游戏对象
	public GameObject  [] Objects;

	//当前加载的进度
	int load_index =0;
	void Start ()
	{
	    //开启一个异步任务,加载模型。
		StartCoroutine(loadObject());
	}

	IEnumerator loadObject()
	{
		//便利所有游戏对象
		foreach(GameObject obj in Objects)
		{
			//激活游戏对象
			obj.active = true;
			//记录当前加载的对象
			load_index ++;

			//这里可以理解为通知主线程刷新UI
			yield return 0;
		}
		//全部便利完毕返回
		yield return 0;
	}

	void OnGUI ()
	{
	    //显示加载的进度
		GUILayout.Box("当前加载的对象ID是: " + load_index);
	}
}

如下图所示,我们把需要加载的游戏对象以数组的形式放在Objects数组中,因为这些对象属于未激活状态,所以不能通过Find 等方法在脚步那种中找到他们。讲到这里我们在说说 编辑器赋值与代码中赋值的区别,编辑器中赋值所消耗的时间都会记在loadlevel ()读取场景中。而代码中使用Resource.load()这类方法所消耗的时间会记在脚本中。开发中还得自行的把握一下把loading加在那里。

 

 

当然我们还可以使用Instantiate(prefab);方法来动态的创建游戏对象。

Main.cs 把它挂在摄像机中。

[代码]:

using UnityEngine;
using System.Collections;

public class Main : MonoBehaviour
 {

	public int count;
	//在编辑器中预设一个游戏对象
	public  GameObject prefab;

	void Start ()
	{
		StartCoroutine(loaditem());
	}

	void OnGUI()
	{
		GUILayout.Box("游戏对象已经加载到 : " + count);
	}

	IEnumerator loaditem()
	{
		//开始加载游戏对象
		for(int i =0; i< 1000; i++)
		{

			Instantiate(prefab);
			count = i;
			//可以理解为刷新UI,显示新加载的游戏对象
			yield return 0;
		}
		//结束
		yield return 0;
	}
}

运行游戏后该游戏对象会循环1000遍逐个创建,不影响主线程。那么今天我们其实学习最多的就是StartCoroutine(),其实就是开启一个异步线程,这里可能有朋友会问Thread可以代替它吗? 答案是不行, 比如查询数据库的时候如果用Thread的话Unity就会报错说不能在线程中查询,但是在StartCoroutine()中就可以完成,所以开发中大家可以尝试着使用它,我们还可以使用StopCoroutine(“name”)来关闭一个正在执行的异步线程。

时间: 2024-12-02 19:57:07

[Unity3D]异步加载游戏场景与异步加载游戏资源进度条的相关文章

视图的加载过程有点慢,我想加入一个进度条,请问该如何操作?

问题描述 DataGridView1.DataSource=myDataview这个加载过程有点慢,我想加入一个进度条,请问该如何操作? 解决方案 解决方案二:怎么没人回答呢?难道我的问题问得不好?解决方案三:DataGridView1.DataSource=myDataview加入一个进度条,可能需要记录总量,而且每获取一个记录需要刷新一次,不建议这样做:建议加入一个loadingGIF:具体多线程,MSDN里面好多.解决方案四:请问这个多线程该如何使用啊?解决方案五:OptionExplic

IOS swift 异步加载数据,并显示一个进度条

问题描述 IOS swift 异步加载数据,并显示一个进度条 网络获取数据使用的是NSURLConnection,异步请求.这个数据已经能够获得了.现在想要实现的是,通过登录界面输入账号什么的,点击提交按钮可以在显示进度条的同时执行post请求得到数据,如果这个数据不为空进度条消失并登录成功回到主界面,否者就提示有错. 希望小伙伴给个简单的例子,这样会更好理解 这个在安卓中是用AsyncTask实现的..线程一直都理不清,还请小伙伴们多多指导.谢谢!!!!! 解决方案 http://www.it

json解析,异步下载(listview仅滑动时加载)Demo总结

异步加载的练习demo 主要涉及知识点: 1.解析json格式数据,主要包括图片,文本 2.使用AsynTask异步方式从网络下载图片 3.BaseAdapter的"优雅"使用 4.使用Lru缓存算法 5.改进加载:仅在listview滑动停止后才加载可见项,滑动中不加载 具体代码可以参看http://download.csdn.net/detail/xsf50717/9169621 涉及到的知识点如上,这里做一个小结,仅对一些代码片段分析 1.异步加载 主要有俩个原因 [1]Andr

如何解决estjs中异步数据加载失败问题(加载数据超时导致数据加载失败),或延长extjs异步数据加载时间?

问题描述 如何解决estjs中异步数据加载失败问题(加载数据超时导致数据加载失败),或延长extjs异步数据加载时间? 问题补充:lizhi92574 写道 解决方案 Ext.data.Connection.prototype.timeout='9000';设置ajax请求时间默认30秒解决方案二:对解决方案三:你加载多大的数据居然超时了?

浅析JS异步加载进度条_javascript技巧

展现效果: 1) 当点击Load的时候,模拟执行异步加载. 浏览器被遮挡. 进度条出现. 实现思路: 1.当用户点击load button执行异步请求. 调用方法 出现加载条 2.怎么实现进度条呢? 1) 在document.body 新增一个div.覆盖浏览器. 设置背景会灰色. z-index = 999. 加载的时候让用户无法修改界面值 2) 在document.body 新增一个动态的div. 代码实现: Main.html: <!DOCTYPE html> <html>

我的Android进阶之旅------&amp;gt;Android疯狂连连看游戏的实现之加载界面图片和实现游戏Activity(四)

正如在<我的Android进阶之旅------>Android疯狂连连看游戏的实现之状态数据模型(三)>一文中看到的,在AbstractBoard的代码中,当程序需要创建N个Piece对象时,程序会直接调用ImageUtil的getPlayImages()方法去获取图片,该方法会随机从res/drawable目录中取得N张图片. 下面是res/drawable目录视图: 为了让getPlayImages()方法能随机从res/drawable目录中取得N张图片,具体实现分为以下几步: 通

android handler-Handler和异步任务的应用场景和关系

问题描述 Handler和异步任务的应用场景和关系 Handler和异步任务各有哪些优点和缺点,他们应用的场合有哪些些? 解决方案 Handlerhttp://www.cnblogs.com/angeldevil/p/3340644.html 异步主要用于执行一个长时间的任务(计算.下载.等待消息.定时执行等)不等执行完,执行后面的代码.

网页进度条设计:关于讨论loading加载后的一些心得

文章描述:Loading,让烦躁少一些. 前一阵子,接到一个app切图制作加载圆形进度条的任务,看到那个小进度条转啊转的,我若有所思-同时,一个做印象派制作间控件设计的同学最近做了改版,那个控件登陆需要一些时间,看到他对loading加载条进行了优化,然后就一起交流了一下.作为一个刚毕业入行不久的新人,请允许我分享一下关于讨论loading加载后的一些心得- 这是一个浮躁的年代,长听到这样的抱怨"好慢!""等到死!",每次看到那个转啊转的圈圈,或者是那个"

ajax 异步上传带进度条视频并提取缩略图_AJAX相关

最近在做一个集富媒体功能于一身的项目.需要上传视频.这里我希望做成异步上传,并且有进度条,响应有状态码,视频连接,缩略图. 服务端响应 { "thumbnail": "/slsxpt//upload/thumbnail/fdceefc.jpg", "success": true, "link": "/slsxpt//upload/video/fdceefc.mp" } 并且希望我的input file控件不