版權(quán)聲明:本文由秦元培創(chuàng)作和發(fā)表,采用署名(BY)-非商業(yè)性使用(NC)-相同方式共享(SA)國際許可協(xié)議進行許可,轉(zhuǎn)載請注明作者及出處,本文作者為秦元培,本文標題為在Unity3D中加載外部圖片的兩種方法,本文鏈接為http://qinyuanpei.com/2015/10/08/2-methods-to-load-image-in-unity3d/.
各位朋友大家好,我是秦元培,歡迎大家關(guān)注我的博客。最近在做項目的過程中遇到這樣的一個需求:玩家可以在游戲過程中進行實時存檔,在存檔過程中會保存當前游戲進度,同時會截取當前游戲畫面并加載到游戲存檔界面中。當下一次進入游戲的時候,將讀取本地存檔圖片并加載到游戲界面中。這在單機游戲中是特別常見的一種功能,這里主要有兩個關(guān)鍵點。首先是截取游戲畫面,這個問題大家可以在《Unity3D游戲開發(fā)之截屏保存精彩瞬間》這篇文章中找到答案。其次是從本地加載圖片,因為這里要保證可讀可寫,因此傳統(tǒng)的Resources.Load()方式和AssetBundle方式均無法實現(xiàn)這樣的功能。那么怎樣從外部加載圖片到游戲中,這就是我們今天要討論的內(nèi)容啦。好了,這里介紹兩種方法來實現(xiàn)這一目的。
喜聞樂見的WWW方式
喜聞樂見的WWW方式之所以喜聞樂見,這是因為這是我們最為熟悉的一種,我們都知道通過WWW可以從網(wǎng)絡(luò)上加載文本、圖片、音頻等形式的內(nèi)容,那么通過WWW能否加載本地外部(相對于應用程序)資源呢?答案是肯定的,這是因為WWW可以支持http和file兩種協(xié)議。我們通常接觸到的WWW默認都是指http協(xié)議,現(xiàn)在我們來說說file協(xié)議,該協(xié)議可以用來訪問本地資源(絕對路徑)。例如我們希望加載文件D:\TestFile\pic001.png這個文件,則此時對應的C#腳本為:
1 2 3 4 5 6 7 8 9
| //請求WWW WWW www = new WWW("file://D:\\TestFile\\pic001.png); yield return www; if(www != null && string.IsNullOrEmpty(www.error)) { //獲取Texture Texture texture=www.texture; //更多操作... }
|
注意到這里出現(xiàn)了yield return結(jié)構(gòu),這表示這里使用到了協(xié)程,因此我們需要付出的代價就是需要在項目中使用StartCoroutine等協(xié)程相關(guān)的方法來調(diào)用這些協(xié)程。雖然在Unity3D中使用協(xié)程是件簡單的事情,可是如果我們隨隨便便地使用協(xié)程而不注意去維護這些協(xié)程,那么這些讓我們引以為傲的簡單代碼可能就會變成我們痛苦不堪的無盡深淵。
亙古不變的傳統(tǒng)IO方式
好了,下面我們隆重推出亙古不變的傳統(tǒng)IO方式,這種方式相信大家都沒有接觸過,所以這里將這種方法和大家分享。既然是傳統(tǒng)的IO方式,那么無非就是各種IO流的處理啦。好,我們一起來看下面這段代碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| //創(chuàng)建文件讀取流 FileStream fileStream = new FileStream(screen, FileMode.Open, FileAccess.Read); fileStream.Seek(0, SeekOrigin.Begin); //創(chuàng)建文件長度緩沖區(qū) byte[] bytes = new byte[fileStream.Length]; //讀取文件 fileStream.Read(bytes, 0, (int)fileStream.Length); //釋放文件讀取流 fileStream.Close(); fileStream.Dispose(); fileStream = null;
//創(chuàng)建Texture int width=800; int height=640; Texture2D texture = new Texture2D(width, height); texture.LoadImage(bytes);
|
可以看到在使用這種方式讀取圖片文件的時候主要是將圖片文件轉(zhuǎn)化為byte[]數(shù)組,再利用Texture2D的LoadImage方法轉(zhuǎn)化為Unity3D中的Texture2D。這種方法需要在創(chuàng)建過程中傳入圖片的大小,在這里我們創(chuàng)建了一張800X640的圖片。經(jīng)過博主的研究發(fā)現(xiàn),這種方式加載外部圖片相對于使用WWW加載外部圖片效率更高,所以如果大家遇到類似的需求,博主個人推薦大家使用這種方式進行加載。
到目前為止我們解決了如何從外部加載圖片到Unity3D中,現(xiàn)在我們回到最開始的問題,我們從外部讀取到這些圖片以后需要將它們加載到游戲界面中。比如當我們使用UGUI的時候,UGUI中的Image控件需要一個Sprite來作為它的填充內(nèi)容,那么此時我們就需要將Texture轉(zhuǎn)化為Sprite.號了,下面我們給出一個簡單的例子:
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 83 84 85 86 87 88
| using UnityEngine; using System.Collections; using UnityEngine.UI; using System.IO;
public class TestLoading : MonoBehaviour { /// <summary> /// Image控件 /// </summary> private Image image;
void Start () { image = this.transform.Find("Image").GetComponent<Image>();
//為不同的按鈕綁定不同的事件 this.transform.Find("LoadByWWW").GetComponent<Button>().onClick.AddListener ( delegate(){LoadByWWW();} );
this.transform.Find("LoadByIO").GetComponent<Button>().onClick.AddListener ( delegate(){LoadByIO();} ); }
/// <summary> /// 以IO方式進行加載 /// </summary> private void LoadByIO() { double startTime = (double)Time.time; //創(chuàng)建文件讀取流 FileStream fileStream = new FileStream("D:\\test.jpg", FileMode.Open, FileAccess.Read); fileStream.Seek(0, SeekOrigin.Begin); //創(chuàng)建文件長度緩沖區(qū) byte[] bytes = new byte[fileStream.Length]; //讀取文件 fileStream.Read(bytes, 0, (int)fileStream.Length); //釋放文件讀取流 fileStream.Close(); fileStream.Dispose(); fileStream = null;
//創(chuàng)建Texture int width = 300; int height = 372; Texture2D texture = new Texture2D(width, height); texture.LoadImage(bytes);
//創(chuàng)建Sprite Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f)); image.sprite = sprite;
startTime=(double)Time.time-startTime; Debug.Log("IO加載用時:" + startTime); }
/// <summary> /// 以WWW方式進行加載 /// </summary> private void LoadByWWW() { StartCoroutine(Load()); }
IEnumerator Load() { double startTime = (double)Time.time; //請求WWW WWW www = new WWW("file://D:\\test.jpg"); yield return www; if(www != null && string.IsNullOrEmpty(www.error)) { //獲取Texture Texture2D texture=www.texture;
//創(chuàng)建Sprite Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f)); image.sprite = sprite;
startTime = (double)Time.time - startTime; Debug.Log("WWW加載用時:" + startTime); } } }
|
現(xiàn)在我們運行程序可以發(fā)現(xiàn)兩種方式均可以讓圖片加載進來,為了對比兩種方式在執(zhí)行效率上的高低,我們在腳本中加入了相關(guān)代碼,通過對比可以發(fā)現(xiàn)使用IO方式加載一張227k的圖片需要的時間為0s,而使用WWW方式加載需要0.0185s,因此傳統(tǒng)的IO方式具有更高的效率,建議大家在遇到這類問題時盡可能地使用這種方式。好了,今天的內(nèi)容就是這樣啦,歡迎大家在我的博客中留言、歡迎大家關(guān)注和支持我的博客,謝謝大家!
版權(quán)聲明:本文由秦元培創(chuàng)作和發(fā)表,采用署名(BY)-非商業(yè)性使用(NC)-相同方式共享(SA)國際許可協(xié)議進行許可,轉(zhuǎn)載請注明作者及出處,本文作者為秦元培,本文標題為在Unity3D中加載外部圖片的兩種方法,本文鏈接為http://qinyuanpei.com/2015/10/08/2-methods-to-load-image-in-unity3d/.
本站僅提供存儲服務,所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請
點擊舉報。