Unity3D截取界面任意位置生成图片并保存
2013-03-04 10:57
274 查看
从事Unity3D开发工作有小一年了吧。这一年里积累了很多开发的经验,做了很多有用的和没有用的东西。
今天开了这个博客,希望能把这些东西慢慢记录下来。
一来可以当做自己的学习笔记见证自己的成长,二来可以和广大的开发工作者一起交流,学习经验。
这次研究的是一个屏幕截取并保存的功能。先上图。
1.Ctrl + Alt + X 开始截图。
2.Enter键执行截屏并弹出保存框。
3.截取后保存的图片。
大致的思路是这样:
1.GL类执行界面选框的显示。
2.用Texture2D类设置新的像素块颜色。
3.System.Windows.forms.dll弹出保存对话框,保存图片文件并打开。
难点在于GL框的绘制逻辑以及新的图片生成时屏幕坐标的计算。
代码如下:
ScreenShot类
ScreenShotControl类
阐述几个开发中的问题:
1.调用Windows的DLL,需要在Unity里更改一下设置。
File -> Build Settings -> Player Settings ->Other Settings -> Optimization -> Api Compatibility Level 更改为 .NET 2.0。
2.在执行完截屏操作后,虽然能够成功生成图片,但是会报一个错。
ReadPixels was called to read pixels from system frame buffer, while not inside drawing frame.
如果有高手知道具体的解决办法,请指教一下。
3.程序的代码结构写的不是太好,请高手指正。
工程包地址:http://www.vdisk.cn/down/index/12475143
今天开了这个博客,希望能把这些东西慢慢记录下来。
一来可以当做自己的学习笔记见证自己的成长,二来可以和广大的开发工作者一起交流,学习经验。
这次研究的是一个屏幕截取并保存的功能。先上图。
1.Ctrl + Alt + X 开始截图。
2.Enter键执行截屏并弹出保存框。
3.截取后保存的图片。
大致的思路是这样:
1.GL类执行界面选框的显示。
2.用Texture2D类设置新的像素块颜色。
3.System.Windows.forms.dll弹出保存对话框,保存图片文件并打开。
难点在于GL框的绘制逻辑以及新的图片生成时屏幕坐标的计算。
代码如下:
ScreenShot类
using UnityEngine; using System.Collections; using System.Windows.Forms; using System.IO; using System.Text; //截屏工具 public class ScreenShot : MonoBehaviour { //选框材质 public Material mat; //初始位置 Vector3 startPos = Vector3.zero; //结束位置 Vector3 endPos = Vector3.zero; //是否绘制 bool isDraw = false; //是否清除 bool isClear = true; void Update () { //左键按下开始绘制 if(Input.GetMouseButtonDown(0)) { isDraw = true; isClear = true; startPos = Input.mousePosition; } //左键松开GL框悬停 if(Input.GetMouseButtonUp(0)) { //鼠标原位置点击不做GL绘制 if(endPos == startPos) { isDraw = false; } isClear = false; } //右键按下重新绘制 if(Input.GetMouseButtonDown(1)) { isDraw = false; enabled = false; } //Enter键按下执行截屏 if(Input.GetKeyDown(KeyCode.Return) && isDraw && !isClear) { isDraw = false; StartCoroutine(DoScreenShot(new Vector2(startPos.x,UnityEngine.Screen.height - startPos.y),new Vector2(endPos.x,UnityEngine.Screen.height - endPos.y))); enabled = false; } } void OnGUI () { //文本提示 if(!isDraw) { GUI.Label(new Rect(Input.mousePosition.x,UnityEngine.Screen.height - Input.mousePosition.y,100,100)," 请框选截图范围"); } if(isDraw && !isClear && endPos != startPos) { GUI.Label(new Rect(Input.mousePosition.x,UnityEngine.Screen.height - Input.mousePosition.y,100,100)," 按下Enter键截屏"); } } void OnPostRender () { //绘制GL线框 if(!isDraw)return; if(isClear) endPos = Input.mousePosition; GL.PushMatrix(); if(!mat)return; mat.SetPass(0); GL.LoadPixelMatrix(); //绘制GL填充面 GL.Begin(GL.QUADS); GL.Color(new Color(Color.yellow.r,Color.yellow.g,Color.yellow.b,0.1f)); GL.Vertex3(startPos.x,startPos.y,0); GL.Vertex3(endPos.x,startPos.y,0); GL.Vertex3(endPos.x,endPos.y,0); GL.Vertex3(startPos.x,endPos.y,0); GL.End(); //绘制GL边框线 GL.Begin(GL.LINES); GL.Color(Color.red); GL.Vertex3(startPos.x,startPos.y,0); GL.Vertex3(endPos.x,startPos.y,0); GL.Vertex3(endPos.x,startPos.y,0); GL.Vertex3(endPos.x,endPos.y,0); GL.Vertex3(endPos.x,endPos.y,0); GL.Vertex3(startPos.x,endPos.y,0); GL.Vertex3(startPos.x,endPos.y,0); GL.Vertex3(startPos.x,startPos.y,0); GL.End(); GL.PopMatrix(); } //截屏 IEnumerator DoScreenShot (Vector2 startPos,Vector2 endPos) { Debug.Log(new Rect(startPos.x < endPos.x ? startPos.x : endPos.x,startPos.y < endPos.y ? UnityEngine.Screen.height - endPos.y : UnityEngine.Screen.height - startPos.y,Mathf.Abs(endPos.x - startPos.x - 2),Mathf.Abs(endPos.y - startPos.y - 2))); yield return new WaitForSeconds(1); Texture2D tex = new Texture2D((int)Mathf.Abs(endPos.x - startPos.x - 2),(int)Mathf.Abs(endPos.y - startPos.y - 2),TextureFormat.RGB24,false); tex.ReadPixels (new Rect(startPos.x < endPos.x ? startPos.x : endPos.x,startPos.y < endPos.y ? UnityEngine.Screen.height - endPos.y : UnityEngine.Screen.height - startPos.y,Mathf.Abs(endPos.x - startPos.x - 2),Mathf.Abs(endPos.y - startPos.y - 2)),0,0); tex.Apply(); Destroy(tex); SaveScreenShot(tex); } //保存文件 void SaveScreenShot (Texture2D tex) { //先将文件保存在工程目录下(其实可以不用这么做) byte[] bytes = tex.EncodeToPNG(); string filename = System.DateTime.Now.Year.ToString("0000") + System.DateTime.Now.Month.ToString("00") + System.DateTime.Now.Day.ToString("00") + System.DateTime.Now.Hour.ToString("00") + System.DateTime.Now.Minute.ToString("00") + System.DateTime.Now.Second.ToString("00") + Random.Range(0,9999).ToString("0000"); string oldFilePath = UnityEngine.Application.dataPath + "/" + filename + ".png"; FileStream f =new FileStream(oldFilePath,FileMode.Create); f.Write(bytes,0,bytes.Length); f.Flush(); f.Close(); System.GC.Collect(); Resources.UnloadUnusedAssets(); //弹出文件保存对话框,调用的是WINDOWS的DLL. SaveFileDialog dialog = new SaveFileDialog(); dialog.Filter = "png|*.png"; string newFilePath = ""; if (dialog.ShowDialog() == DialogResult.OK) { newFilePath = dialog.FileName; } if(newFilePath != "") { if(File.Exists(newFilePath)) { File.Delete(newFilePath); } File.Move(oldFilePath, newFilePath); UnityEngine.Application.OpenURL(newFilePath); } else { File.Delete(oldFilePath); } } }
ScreenShotControl类
using UnityEngine; using System.Collections; //截屏控制 public class ScreenShotControl : MonoBehaviour { ScreenShot screenshot; // Use this for initialization void Start () { screenshot = GetComponent<ScreenShot>(); } // Update is called once per frame void Update () { } void OnGUI () { //Ctrl + Alt + X 执行截屏 if(Event.current.Equals(Event.KeyboardEvent("^&X"))) { screenshot.enabled = true; } } }
阐述几个开发中的问题:
1.调用Windows的DLL,需要在Unity里更改一下设置。
File -> Build Settings -> Player Settings ->Other Settings -> Optimization -> Api Compatibility Level 更改为 .NET 2.0。
2.在执行完截屏操作后,虽然能够成功生成图片,但是会报一个错。
ReadPixels was called to read pixels from system frame buffer, while not inside drawing frame.
如果有高手知道具体的解决办法,请指教一下。
3.程序的代码结构写的不是太好,请高手指正。
工程包地址:http://www.vdisk.cn/down/index/12475143
相关文章推荐
- C#截取当前屏幕界面作为图片保存
- 截图:截取当前程序的界面,并保存到bmp图片中。
- C#截取当前屏幕界面作为图片保存
- javacpp-opencv图像处理之1:实时视频添加文字水印并截取视频图像保存成图片,实现文字水印的字体、位置、大小、粗度、翻转、平滑等操作
- javacpp-opencv图像处理之1:实时视频添加文字水印并截取视频图像保存成图片,实现文字水印的字体、位置、大小、粗度、翻转、平滑等操作
- 使用ReadPixels方法,实现对游戏截取任意位置的屏幕,以及保存和显示截取结果
- 以图片的中心为基准,按照任意尺寸自动调整大小并截取出规定的素材,保存为缩略图或以php形式输出为图片
- Unity3d 截取窗体图片并保存
- 截图:截取当前程序的界面,并保存到bmp图片中。
- 截取多个视频生成批量图片并批量命名保存的matlab实现
- unity3d任意图片截取和裁剪
- mfc 截取桌面 并保存为 bmp 图片
- CODE ---代码助手 (保存代码、搜代码、生成网页、自由界面)
- 将一张图片生成多张缩略图并保存
- Java截取图片的一部分并保存为40*40的图片
- 截取HTML中代码块生成图片
- JAVA 按任意角度旋转图片,并生成新的旋转后图片(转自:http://www.hackchina.com/r/21265/RotateImage.java__html)
- iphone(objective-c)相当于j2me的drawRegion方法 截取部分图片显示到指定位置
- 根据传入的文字生成图片 并保存
- Java实现头像截取裁剪后图片保存,获取的是base64数据,怎么转换为图片并保存到数据库。