喜闻乐见的WWW方式
喜闻乐见的WWW方式之所以喜闻乐见,这是因为这是我们最为熟悉的一种,我们都知道通过WWW可以从网络上加载文本、图片、音频等形式的内容,那么通过WWW能否加载本地外部(相对于应用程序)资源呢?答案是肯定的,这是因为WWW可以支持http和file两种协议。我们通常接触到的WWW默认都是指http协议,现在我们来说说file协议,该协议可以用来访问本地资源(绝对路径)。例如我们希望加载文件D:\TestFile\pic001.png这个文件,则此时对应的C#脚本为:
1 2 3 4 5 6 7 8 9
|
WWW www = new WWW("file: yield return www; if(www != null && string.IsNullOrEmpty(www.error)) { Texture texture=www.texture; }
|
注意到这里出现了yield return结构,这表示这里使用到了协程,因此我们需要付出的代价就是需要在项目中使用StartCoroutine等协程相关的方法来调用这些协程。虽然在Unity3D中使用协程是件简单的事情,可是如果我们随随便便地使用协程而不注意去维护这些协程,那么这些让我们引以为傲的简单代码可能就会变成我们痛苦不堪的无尽深渊。
亘古不变的传统IO方式
好了,下面我们隆重推出亘古不变的传统IO方式,这种方式相信大家都没有接触过,所以这里将这种方法和大家分享。既然是传统的IO方式,那么无非就是各种IO流的处理啦。好,我们一起来看下面这段代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
FileStream fileStream = new FileStream(screen, FileMode.Open, FileAccess.Read); fileStream.Seek(0, SeekOrigin.Begin);
byte[] bytes = new byte[fileStream.Length];
fileStream.Read(bytes, 0, (int)fileStream.Length);
fileStream.Close(); fileStream.Dispose(); fileStream = null;
int width=800; int height=640; Texture2D texture = new Texture2D(width, height); texture.LoadImage(bytes);
|
可以看到在使用这种方式读取图片文件的时候主要是将图片文件转化为byte[]数组,再利用Texture2D的LoadImage方法转化为Unity3D中的Texture2D。这种方法需要在创建过程中传入图片的大小,在这里我们创建了一张800X640的图片。经过博主的研究发现,这种方式加载外部图片相对于使用WWW加载外部图片效率更高,所以如果大家遇到类似的需求,博主个人推荐大家使用这种方式进行加载。
到目前为止我们解决了如何从外部加载图片到Unity3D中,现在我们回到最开始的问题,我们从外部读取到这些图片以后需要将它们加载到游戏界面中。比如当我们使用UGUI的时候,UGUI中的Image控件需要一个Sprite来作为它的填充内容,那么此时我们就需要将Texture转化为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 { 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();} ); }
private void LoadByIO() { double startTime = (double)Time.time; FileStream fileStream = new FileStream("D:\\test.jpg", FileMode.Open, FileAccess.Read); fileStream.Seek(0, SeekOrigin.Begin); byte[] bytes = new byte[fileStream.Length]; fileStream.Read(bytes, 0, (int)fileStream.Length); fileStream.Close(); fileStream.Dispose(); fileStream = null;
int width = 300; int height = 372; Texture2D texture = new Texture2D(width, height); texture.LoadImage(bytes);
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); }
private void LoadByWWW() { StartCoroutine(Load()); }
IEnumerator Load() { double startTime = (double)Time.time; WWW www = new WWW("file://D:\\test.jpg"); yield return www; if(www != null && string.IsNullOrEmpty(www.error)) { Texture2D texture=www.texture;
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); } } }
|
现在我们运行程序可以发现两种方式均可以让图片加载进来,为了对比两种方式在执行效率上的高低,我们在脚本中加入了相关代码,通过对比可以发现使用IO方式加载一张227k的图片需要的时间为0s,而使用WWW方式加载需要0.0185s,因此传统的IO方式具有更高的效率,建议大家在遇到这类问题时尽可能地使用这种方式。好了,今天的内容就是这样啦,欢迎大家在我的博客中留言、欢迎大家关注和支持我的博客,谢谢大家!