溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

[Unity3D]異步加載游戲場景與異步加載游戲資源進(jìn)度條

發(fā)布時間:2020-06-30 21:47:08 來源:網(wǎng)絡(luò) 閱讀:743 作者:蓬萊仙羽 欄目:游戲開發(fā)
摘要: 異步任務(wù)相信大家應(yīng)該不會陌生,那么本章內(nèi)容MOMO將帶領(lǐng)大家學(xué)習(xí)Unity中的一些異步任務(wù)。在同步加載游戲場景的時候通常會使用方法 Application.LoadLevel(“yourScene”); 這句代碼執(zhí)行完畢后程序會干什么呢??如下 ...

    異步任務(wù)相信大家應(yīng)該不會陌生,那么下面介紹一下Unity中的一些異步任務(wù)。在同步加載游戲場景的時候通常會使用方法 Application.LoadLevel(“yourScene”);  這句代碼執(zhí)行完畢后程序會干什么呢??如下圖所示,這是我隨便找了一個游戲場景, 在Hierarchy視圖中我們可以看到該場景中“天生”的所有游戲?qū)ο?。天生的意思就是運(yùn)行程序前該場景中就已經(jīng)存在的所有游戲?qū)ο?。然后這些對象就會在執(zhí)行完Application.LoadLevel(“yourScene”);方法后加載至內(nèi)存當(dāng)中。如果該場景中的游戲?qū)ο筮^多那么瞬間將會出現(xiàn)卡一下的情況,因?yàn)?span >LoadLevel()方法是同步進(jìn)行的。MOMO把這種加載起個名字叫A形式加載。

 

[Unity3D]異步加載游戲場景與異步加載游戲資源進(jìn)度條

 

下面我說說“后天“加載的游戲?qū)ο?。意思是這些游戲?qū)ο笫峭ㄟ^腳本動態(tài)的創(chuàng)建出來的。比如常用方法 :

[代碼]

GameObject Obj = (GameObject)Instantiate(prefab);

這句代碼執(zhí)行完畢后同樣會在Hierarchy視圖中添加對應(yīng)的游戲?qū)ο?。MOMO把這種加載起個名字叫B形式加載。

 

下面我們學(xué)習(xí)異步加載游戲場景,異步異步顧名思義就是不影響當(dāng)前游戲場景的前提下加載新場景。通常異步加載的方式分為兩種:第一種是異步加載新游戲場景,當(dāng)新場景加載完成后進(jìn)入新場景并且銷毀之前的場景。第二種:同樣異步加載新場景,新場景加載完畢后,保留舊場景的游戲?qū)ο蟛⑶疫M(jìn)入新場景。 這里加載的內(nèi)容就是上面提到的A形式加載。然后B形式加載不會記入這里的加載。

第一種異步加載游戲場景對應(yīng)的方法是:

[代碼]:

Application.LoadLevelAsync("yourScene");

這兩種方法加載的方式完全一樣。異步加載其實(shí)重要還是應(yīng)用于游戲LOADING界面,畢竟LOADING如果采用同步的機(jī)制會影響用戶體驗(yàn),說到這里MOMO告訴大家如何在Unity中制作游戲進(jìn)度條。我們應(yīng)當(dāng)在Unity中創(chuàng)建一個專門用于讀取進(jìn)度的場景,假設(shè)A場景到C場景,我們應(yīng)當(dāng)讓A場景先到讀取進(jìn)度的場景B場景,當(dāng)異步任務(wù)完成后在進(jìn)入C場景。 A – 》B -》 C ,在B場景中繪制游戲進(jìn)度條或讀取動畫。因?yàn)锽場景僅僅是個顯示LOADING動畫的場景,所以讀取該場景是瞬間就完成的。

程序在切換場景時應(yīng)當(dāng)有一個全全局的靜態(tài)變量來記錄簡要讀取的場景名稱。這里簡單的寫一下。

[代碼]:

using UnityEngine; using System.Collections;  public class Globe {          //在這里記錄當(dāng)前切換場景的名稱 	 public static string loadName; }
在A場景中通過某些觸發(fā)條件 調(diào)用LoadLevel進(jìn)入B場景。

[代碼]:

//記錄LOADING場景中需要讀取的C場景名稱 Globe.loadName = "C"; //先進(jìn)入B場景 Application.LoadLevel ("B");
OK我們在B場景中異步讀取C場景與 播放讀取動畫,Loading.cs 綁定在B場景的攝像機(jī)對象身上。當(dāng)C場景異步讀取完畢后即可直接進(jìn)入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;  	//讀取場景的進(jìn)度,它的取值范圍在0 - 1 之間。 	int progress = 0;  	void Start() 	{ 		//在這里開啟一個異步任務(wù), 		//進(jìn)入loadScene方法。 	  	StartCoroutine(loadScene()); 	}  	//注意這里返回值一定是 IEnumerator 	IEnumerator loadScene() 	{ 		//異步讀取場景。 		//Globe.loadName 就是A場景中需要讀取的C場景名稱。 		async = Application.LoadLevelAsync(Globe.loadName);  		//讀取完畢后返回, 系統(tǒng)會自動進(jìn)入C場景 		yield return async;  	}  	void OnGUI() 	{ 		//因?yàn)樵诋惒阶x取場景, 		//所以這里我們可以刷新UI 		DrawAnimation(animations);  	}  	void Update() 	{  		//在這里計(jì)算讀取的進(jìn)度, 		//progress 的取值范圍在0.1 - 1之間, 但是它不會等于1 		//也就是說progress可能是0.9的時候就直接進(jìn)入新場景了 		//所以在寫進(jìn)度條的時候需要注意一下。 		//為了計(jì)算百分比 所以直接乘以100即可 		progress =  (int)(async.progress *100);  		//有了讀取進(jìn)度的數(shù)值,大家可以自行制作進(jìn)度條啦。 		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] );          //在這里顯示讀取的進(jìn)度。 		GUI.Label(new Rect( 100,180,300,60), "lOADING!!!!!" + progress);  	}  }

OK 下面我們繼續(xù)學(xué)習(xí)在游戲場景中加載對象,文章的開始MOMO已經(jīng)告訴大家,游戲場景中Hierarchy視圖中的所有的對象在切換場景的時候都會加載。其實(shí)有一種方法可以讓某些游戲?qū)ο蟛粫患虞d,如下圖所示,首先在Hierarchy視圖中選擇一個游戲?qū)ο?,在右?cè)監(jiān)測面板視圖中我們可以看到一個 “小對勾”默認(rèn)情況下是勾選狀態(tài),說明該游戲?qū)ο筇幱诩せ顮顟B(tài),如果點(diǎn)掉的話該對象將被隱藏。這個小功能在開發(fā)中其實(shí)用處非常大,請大家務(wù)必記住哈。

 

[Unity3D]異步加載游戲場景與異步加載游戲資源進(jìn)度條

 

此時此刻大家相像一個游戲場景,默認(rèn)進(jìn)入的時候是沒有任何游戲?qū)ο蟮模缓筮\(yùn)行游戲時開啟一個異步任務(wù)將它們一個一個的加載顯示出來,這種方式適合異步的加載一個比較大的游戲場景。

Test.cs 把它掛在攝像機(jī)對象中。

[代碼]:

using UnityEngine; using System.Collections;  public class Test : MonoBehaviour {  	//這里是需要加載激活的游戲?qū)ο?	public GameObject  [] Objects;  	//當(dāng)前加載的進(jìn)度 	int load_index =0; 	void Start () 	{ 	    //開啟一個異步任務(wù),加載模型。 		StartCoroutine(loadObject()); 	}  	IEnumerator loadObject() 	{ 		//便利所有游戲?qū)ο?		foreach(GameObject obj in Objects) 		{ 			//激活游戲?qū)ο?			obj.active = true; 			//記錄當(dāng)前加載的對象 			load_index ++;  			//這里可以理解為通知主線程刷新UI 			yield return 0; 		} 		//全部便利完畢返回 		yield return 0; 	}  	void OnGUI () 	{ 	    //顯示加載的進(jìn)度 		GUILayout.Box("當(dāng)前加載的對象ID是: " + load_index); 	} }

如下圖所示,我們把需要加載的游戲?qū)ο笠詳?shù)組的形式放在Objects數(shù)組中,因?yàn)檫@些對象屬于未激活狀態(tài),所以不能通過Find 等方法在腳步那種中找到他們。講到這里我們在說說 編輯器賦值與代碼中賦值的區(qū)別,編輯器中賦值所消耗的時間都會記在loadlevel ()讀取場景中。而代碼中使用Resource.load()這類方法所消耗的時間會記在腳本中。開發(fā)中還得自行的把握一下把loading加在那里。

 

[Unity3D]異步加載游戲場景與異步加載游戲資源進(jìn)度條

 

當(dāng)然我們還可以使用Instantiate(prefab);方法來動態(tài)的創(chuàng)建游戲?qū)ο蟆?/span>

Main.cs 把它掛在攝像機(jī)中。

[代碼]:

using UnityEngine; using System.Collections;  public class Main : MonoBehaviour  {  	public int count; 	//在編輯器中預(yù)設(shè)一個游戲?qū)ο?	public  GameObject prefab;  	void Start () 	{ 		StartCoroutine(loaditem()); 	}  	void OnGUI() 	{ 		GUILayout.Box("游戲?qū)ο笠呀?jīng)加載到 : " + count); 	}  	IEnumerator loaditem() 	{ 		//開始加載游戲?qū)ο?		for(int i =0; i< 1000; i++) 		{  			Instantiate(prefab); 			count = i; 			//可以理解為刷新UI,顯示新加載的游戲?qū)ο?			yield return 0; 		} 		//結(jié)束 		yield return 0; 	} }
運(yùn)行游戲后該游戲?qū)ο髸h(huán)1000遍逐個創(chuàng)建,不影響主線程。那么今天我們其實(shí)學(xué)習(xí)最多的就是StartCoroutine(),其實(shí)就是開啟一個異步線程,這里可能有朋友會問Thread可以代替它嗎? 答案是不行, 比如查詢數(shù)據(jù)庫的時候如果用Thread的話Unity就會報錯說不能在線程中查詢,但是在StartCoroutine()中就可以完成,所以開發(fā)中大家可以嘗試著使用它,我們還可以使用StopCoroutine(“name”)來關(guān)閉一個正在執(zhí)行的異步線程。
向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI