来自 Csdn PayneQin

原文:http://blog.csdn.net/qinyuanpei/article/details/49000907

最近在做项目的过程中遇到这样的一个需求:玩家可以在游戏过程中进行实时存档,在存档过程中会保存当前游戏进度,同时会截取当前游戏画面并加载到游戏存档界面中。当下一次进入游戏的时候,将读取本地存档图片并加载到游戏界面中。这在单机游戏中是特别常见的一种功能,这里主要有两个关键点。首先是截取游戏画面,这个问题大家可以在《Unity3D游戏开发之截屏保存精彩瞬间》这篇文章中找到答案。其次是从本地加载图片,因为这里要保证可读可写,因此传统的Resources.Load()方式和AssetBundle方式均无法实现这样的功能。那么怎样从外部加载图片到游戏中,这就是我们今天要讨论的内容啦。好了,这里介绍两种方法来实现这一目的。

喜闻乐见的WWW方式

  喜闻乐见的WWW方式之所以喜闻乐见,这是因为这是我们最为熟悉的一种,我们都知道通过WWW可以从网络上加载文本、图片、音频等形式的内容,那么通过WWW能否加载本地外部(相对于应用程序)资源呢?答案是肯定的,这是因为WWW可以支持http和file两种协议。我们通常接触到的WWW默认都是指http协议,现在我们来说说file协议,该协议可以用来访问本地资源(绝对路径)。例如我们希望加载文件D:\TestFile\pic001.png这个文件,则此时对应的C#脚本为:

//请求WWW
WWW www = new WWW("file://D:\\TestFile\\pic001.png);
yield return www;
if(www != null && string.IsNullOrEmpty(www.error))
{//获取TextureTexture texture=www.texture;   //更多操作...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

注意到这里出现了yield return结构,这表示这里使用到了协程,因此我们需要付出的代价就是需要在项目中使用StartCoroutine等协程相关的方法来调用这些协程。虽然在Unity3D中使用协程是件简单的事情,可是如果我们随随便便地使用协程而不注意去维护这些协程,那么这些让我们引以为傲的简单代码可能就会变成我们痛苦不堪的无尽深渊。

亘古不变的传统IO方式

  好了,下面我们隆重推出亘古不变的传统IO方式,这种方式相信大家都没有接触过,所以这里将这种方法和大家分享。既然是传统的IO方式,那么无非就是各种IO流的处理啦。好,我们一起来看下面这段代码:

//创建文件读取流
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;//创建Texture
int width=800;
int height=640;
Texture2D texture = new Texture2D(width, height);
texture.LoadImage(bytes);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

可以看到在使用这种方式读取图片文件的时候主要是将图片文件转化为byte[]数组,再利用Texture2D的LoadImage方法转化为Unity3D中的Texture2D。这种方法需要在创建过程中传入图片的大小,在这里我们创建了一张800X640的图片。经过博主的研究发现,这种方式加载外部图片相对于使用WWW加载外部图片效率更高,所以如果大家遇到类似的需求,博主个人推荐大家使用这种方式进行加载。

  到目前为止我们解决了如何从外部加载图片到Unity3D中,现在我们回到最开始的问题,我们从外部读取到这些图片以后需要将它们加载到游戏界面中。比如当我们使用UGUI的时候,UGUI中的Image控件需要一个Sprite来作为它的填充内容,那么此时我们就需要将Texture转化为Sprite.号了,下面我们给出一个简单的例子:

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;//创建文件读取流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;//创建Textureint width = 300;int height = 372;Texture2D texture = new Texture2D(width, height);texture.LoadImage(bytes);//创建SpriteSprite 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;//请求WWWWWW www = new WWW("file://D:\\test.jpg");yield return www;        if(www != null && string.IsNullOrEmpty(www.error)){//获取TextureTexture2D texture=www.texture;//创建SpriteSprite 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);}}
}
  • 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
  • 89

  现在我们运行程序可以发现两种方式均可以让图片加载进来,为了对比两种方式在执行效率上的高低,我们在脚本中加入了相关代码,通过对比可以发现使用IO方式加载一张227k的图片需要的时间为0s,而使用WWW方式加载需要0.0185s,因此传统的IO方式具有更高的效率,建议大家在遇到这类问题时尽可能地使用这种方式。

Unity 中 Png转Texture2D再转Sprite相关推荐

  1. Unity中导入外部模型与预制件

    前言: 在Unity3D的 Asset Store  中下载的包(package)资源, 其默认位置是: C:\Users\用户名\AppData\Roaming\Unity\Asset Store- ...

  2. 【个人UNITY笔记】{基础} 2D游戏中使用Shader或Camera解决Sprite前后遮挡关系

    因为个人制作的奇葩游戏2D游戏是用Sprite当作角色和物体,然而Unity里不应该使用带透视的相机来渲染Sprite,因为会2个Sprite距离太近会出现闪烁,但是我就是想保留透视,同时使用Spri ...

  3. Unity教程之再谈Unity中的优化技术

    这是从 Unity教程之再谈Unity中的优化技术 这篇文章里提取出来的一部分,这篇文章让我学到了挺多可能我应该知道却还没知道的知识,写的挺好的 优化几何体 这一步主要是为了针对性能瓶颈中的" ...

  4. unity中请问如何点击一下image(image加了button项)变红色再点击一下按钮变成绿色。一直这么循环变色?急求,望大佬指点emmm。c#代码

    unity中请问如何点击一下image(image加了button项)变红色再点击一下按钮变成绿色.一直这么循环变色?急求,望大佬指点emmm.c#代码

  5. 关于Unity中的UGUI优化,你可能遇到这些问题

    一.界面制作 Q1:UGUI里的这个选项 ,应该是ETC2拆分Alpha通道的意思,但是在使用中并没起作用?请问有没有什么拆分的标准和特别要求呢? 据我们所知,alpha split 的功能最初只对 ...

  6. ugui unity 取消选择_关于Unity中的UGUI优化,你可能遇到这些问题

    ​关键字 界面制作 ​网格重建 ​界面切换 ​加载相关 ​字体 ​ 一.界面制作 Q1:UGUI里的这个选项 ,应该是ETC2拆分Alpha通道的意思,但是在使用中并没起作用?请问有没有什么拆分的标准 ...

  7. 【专栏精选】Unity中的HTTP网络通信

    本文节选自洪流学堂公众号技术专栏<大话Unity2019>,未经允许不可转载. 洪流学堂公众号回复专栏,查看更多专栏文章. 洪流学堂,让你快人几步.你好,我是郑洪智. 大智:"小 ...

  8. 关于Unity中的资源管理,你可能遇到这些问题(UWA报告)

    关键字 AssetBundle 资源制作 纹理\网格\材质\Shader\音频\动画 Lightmap 一.AssetBundle 相关 Q1:Unity中的SerializedFile是怎么产生的? ...

  9. Unity中制作自定义字体的两种方式

    Unity支持自定义图片字体(CustomFont),网上有很多教程,细节不尽相同,当概括起来基本就是两种方式.一是使用BMFont,导出图集和.fnt文件,再使用图集在Unity中设置得到字体.二是 ...

最新文章

  1. CentOS7系统下修改网卡为eth0
  2. matlab mod()rem()
  3. jdk-ant-sphnix4安装
  4. K8S部署工具:KubeOperator安装部署
  5. SQL语句中timestamp进行排序BUG
  6. 循环往list中add对象却总是add的是一个对象
  7. HDU - 1723 - Distribute Message
  8. input之question
  9. flexbox 弹性盒模型
  10. flowable设计器节点属性扩展_gooflow设计器API说明书
  11. vue echarts饼状图百分比展示
  12. 互联网晚报 |11/24 星期四 | 比亚迪涨价2000到6000元不等;苹果15或告别纯直边;星巴克回应0.01元抢券不兑换...
  13. Java爬取喜马拉雅非付费音频【优化】
  14. Android面试题之Activity篇
  15. 雷军成功踏上移动互联网游轮
  16. 如何查看JAVA某个进程下的线程
  17. cad用键盘放大缩小_CAD的放大缩小快捷键是什么?
  18. MySQL--SQL执行顺序详解
  19. unity2020新特性_Unity Hackweek 2020 –无论我们身在何处,
  20. linux交换分区的命令,LInux下的交换分区以及相关查看命令

热门文章

  1. android dao设计模式,DAO设计模式
  2. 力扣——Pow(x, n)
  3. Qt之解决error: member access into incomplete type ‘UI::XXX‘
  4. 怎么设置php 中小窗口浮动,CSS_闭合浮动元素超级简单的方法,无意中看到的一个非常不错的 - phpStudy...
  5. static在内存层面的作用_static关键字总结
  6. SSM-1-SSM整合
  7. 【操作系统/OS笔记15】死锁的系统模型,死锁的处理办法,银行家算法与死锁检验算法
  8. JavaScript对象快速入门
  9. 张敬富审计百度云资源_钟平逻辑英语资源百度云
  10. python中options类_Python的OptionParser模块