Unity异步加载和读取外部图片资源

版权声明:本文为博主原创文章,转载请注明出处 https://blog.csdn.net/u013746357/article/details/83385046

后台线程读取本地或者云端png\jpg图片。


背景:做VR开发中,最经常用到的一个功能就是加载外部的全景图,并且在头盔里显示。但是一张4K的全景图动辄10M左右的大小,而且需要占用24M(4K 的jpg格式,一个像素24bit-RGB)内存。如果在主线程里做加载,会明显感觉到卡顿,而在VR模式下用户对卡顿 的感知会被放大。幸运的时Unity的新版本中为我们提供了在辅助线程(worker thread)完成这个文件加载和图片解析的过程。


使用WWW类或者IO的方式确实可以做到文件加载在后台线程完成,但是当把加载到的数据解析到Texture 类里时,在早先的版本里,只能在主线程做,而且unity会一次分配满足这个图片的内存,并且读取所有像素。这样的行为导致,这个操作是非常耗时的。当然对于小的图片,这样做依然是没有问题的。

  Texture2D tex;
  tex = new Texture2D(4, 4, TextureFormat.DXT1, false);
  using (WWW www = new WWW(url))
  {
      yield return www;
      www.LoadImageIntoTexture(tex);
      GetComponent<Renderer>().material.mainTexture = tex;
		// 或者是下面这样
		// GetComponent<Renderer>().material.mainTexture =www.texture;
  }

上述方式非常简单而且可靠,对于一些小的图片加载也完全没有问题,而且兼容几乎所有的unity版本。假设使用这种方式的话,有一些问题需要注意

  1. 加载的图片长和宽尽量是2的n次方,否则会比期望的浪费更多的内存空间,并且加载速度会更慢
  2. 如果加载出来的图片不再需要了,需要手动Destroy,即使没有引用unity也不会自动GC 回收掉
  3. 如果不需要透明通道,尽量使用jpg格式的图片,而不要使用png,这样可以节省1/4的内存(RGB24->RGBA32)

说完传统的方式加载,我们介绍下Unity新支持的异步加载图片功能,这个在文档里隐藏较深,很多人可能不会发现。

IEnumerator GetTexture() {
	//这里的地址可以填本地文件地址  file://[文件路径]
        using(UnityWebRequest www = 
        	UnityWebRequest.GetTexture("http://www.my-server.com/image.png")) {
            yield return www.Send();
            if(www.isError) {
                Debug.Log(www.error);
            }
            else {
            /*这里把贴图转换的过程放到了后台线程来完成,
            并且相比于直接脚本加载图片做了优化,减少了内存分配*/
                Texture myTexture = DownloadHandlerTexture.GetContent(www);
            }
        }
    }

UnityWebRequest这个类在Unity2018.2.12 里被替换成了UnityWebRequestTexture,但是使用方法是完全一样的。
Unity2018文档地址https://docs.unity3d.com/ScriptReference/Networking.UnityWebRequestTexture.GetTexture.html.

猜你喜欢

转载自blog.csdn.net/u013746357/article/details/83385046