Unity实现截图功能详解

来源:互联网 发布:淘宝优惠券推广渠道 编辑:程序博客网 时间:2024/05/21 19:35

一、截图是经常用到的功能,下面是可能遇到的需求:
1.全屏截图
2.局部截图
3.针对某一相机的截图
4.去除UI元素截图

二、截图可以考虑的方法:

1. Application.CaptureScreenshot(“Screenshot.png”, 0);

截取某一帧时整个游戏的画面,全屏截图。
参数1是图片名称,需加后缀.png;参数二是是否压缩,0不压缩,小于1时压缩,大于1是扩大。
保存路径:工程根目录,editor环境在asset下;android环境在应用程序沙盒中。
优缺点:
实现简单,在任何地方来这么一句就好;
不能针对某一个相机(camera)的画面进行截图。
对局部画面截图,实现起来不方便,效率也低

2.使用Texture2d类下的ReadPixels方法

创建一个空纹理,读取屏幕像素,保存问png文件

private void CaptureScreenshotNormal(Rect rect,string savePath,string fileName)   {    // 先创建一个的空纹理,大小可根据实现需要来设置    Texture2D screenShot = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.RGB24,false);        // 读取屏幕像素信息并存储为纹理数据    screenShot.ReadPixels(rect, 0, 0);    screenShot.Apply();        // 然后将这些纹理数据转成一个png图片文件    byte[] bytes = screenShot.EncodeToPNG();  Destroy (screenShot);//保存图片  string finalPath = savePath + "//" + fileName;  System.IO.File.WriteAllBytes(finalPath, bytes);    Debug.Log("截屏了一张图片:"+finalPath);   }  

3.ReadPixels+摄像机的RenderTexture方法针对某个相机截屏

让ReadPixels读的是某个相机渲染的像素

private void CaptureCamera(Camera camera, Rect rect,string fileName)   {    // 创建一个RenderTexture对象    RenderTexture rt = new RenderTexture((int)rect.width, (int)rect.height, 0);    // 临时设置相关相机的targetTexture为rt, 并手动渲染该相机  camera.targetTexture = rt;    camera.Render();      // 激活这个rt, 并从中中读取像素。    RenderTexture.active = rt;  //一定要激活,不然读取不到像素的  Texture2D screenShot = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.RGB24,false);    screenShot.ReadPixels(rect, 0, 0);// 这个时候,它是从RenderTexture.active中读取像素    screenShot.Apply();    GameObject.Destroy(rt);    // 重置相关参数,以使camera继续在屏幕上显示    camera.targetTexture = null;   RenderTexture.active = null;    // 最后将这些纹理数据转换成一个png图片文件并保存     byte[] bytes = screenShot.EncodeToPNG();    Destroy (screenShot);  System.IO.File.WriteAllBytes(fileName, bytes);    Debug.Log("截屏了一张图片:"+fileName); }  

三、实现上述需求

1.普通全屏截图
使用方法1,不解释;
使用方法2:Rect rect = new Rect (0,0,Screen.width,Screen.height);//全屏

2.普通局部截图
使用方法2:
Rect rect = new Rect (Screen.width/4,Screen.height/4,Screen.width/2,Screen.height/2);//半屏

3.针对某一相机的截图
使用方法3:
在脚本中定义一个public变量:public Camera camera;
想截那个camera就拖哪个

4.去除UI元素截图
a、使用方法3
将管理UI元素的camera和管理场景的camera分开,拖管理场景的camera即可

b、基于NGUI的笨方法
思路:开始截图时先隐藏NGUI中的所有UI元素,然后截图,然后显示NGUI所有UI元素
实现:由于本人目前对显示隐藏不了解,所以用了更笨的方法,把UI root中的UI元素用container包起来,然后给container设计一个tween动画,只要能将container移出UI root的范围即可
这样在截图之前先执行该动画,在截图,最后再反向执行该动画。

代码如下:

public class SimpleCapNoUI : MonoBehaviour { public TweenPosition hideUiTween; //将container拖进来,它对应其绑定的tween动画,开始请设置不可用 public void OnNoUiCapClick(){  //开始截屏  StartCoroutine(CaptureNoUI()); } IEnumerator CaptureNoUI() {  //隐藏所有UI元素,即执行动画  hideUiTween.PlayForward ();  //等待它执行完成 ,我设置的上述动画时间是0.01秒 //此处应该有更好的写法,目前对协程还不是很了解  yield return new WaitForSeconds(0.01f);  //截屏并保存  Rect rect = new Rect (0,0,Screen.width,Screen.height);  string savePath = Application.dataPath;  string fileName = "SimpleCapNoUI.png";  CaptureScreenshotNormal (rect, savePath, fileName);  //显示所有UI元素  hideUiTween.PlayReverse (); } //普通截屏 private void CaptureScreenshotNormal(Rect rect,string savePath,string fileName)   {    // 先创建一个的空纹理,大小可根据实现需要来设置    Texture2D screenShot = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.RGB24,false);        // 读取屏幕像素信息并存储为纹理数据    screenShot.ReadPixels(rect, 0, 0);    screenShot.Apply();        // 然后将这些纹理数据转成一个png图片文件    byte[] bytes = screenShot.EncodeToPNG();  Destroy (screenShot);  string finalPath = savePath + "//" + fileName;  System.IO.File.WriteAllBytes(finalPath, bytes);    Debug.Log("截屏了一张图片:"+finalPath);   }  }

实例图片:

当前game视窗
这里写图片描述

普通全屏截图
这里写图片描述

普通半屏截图
这里写图片描述

使用方法3实现的去除UI截图:注意立方体的位置,为什么?
这里写图片描述

使用方法3实现的只截取UI的截图
这里写图片描述

本人原创的笨方法实现的去UI截图
这里写图片描述

Demo源码

0 0
原创粉丝点击