您好,登錄后才能下訂單哦!
異步任務相信大家應該不會陌生,那么下面介紹一下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; }
[代碼]://記錄LOADING場景中需要讀取的C場景名稱 Globe.loadName = "C"; //先進入B場景 Application.LoadLevel ("B");
[代碼]: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; } } |
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。