1.主要涉及到的知识:Unity3D中Texture2D类操作,开启协程;System.IO文件流操作,Delegate信息回调。
用途:用于屏幕截图
简介:CaptureScreenTool是一个工具类,调用CaptureScreenTool.Instance.saveScreenPic(Delegate callback,ImgType type=ImgType.PNG));可以截屏操作
思路:读取屏幕帧缓存,创建Texture,然后文件写入帧缓存格式化后数据bytes!
文件操作最好写一个文件管理工具类,这里只写出写入byte数组的方法。一次把数据全写入(可以循环分次写入)
- #region FileControl
- class FIleMag
- {
- public static bool saveBytes(string path, byte[] bytes)
- {
- bool res = false;
- if (path == null || bytes == null)
- return false;
- if (!Directory.Exists(Path.GetDirectoryName(path)))//得到文件的所在目录的全路径,没有该目录就创建
- Directory.CreateDirectory(path);
- FileStream fs = null;
- try
- {
- fs = new FileStream(path, FileMode.Create);//创建新的文件
- fs.Write(bytes, 0, bytes.Length);//一次写入所有byte[]
- fs.Flush();
- fs.Close();
- res = true;
- }
- catch (Exception ex)
- {
- Debug.Log(ex);
- return false;
- }
- return res;
- }
- }
- #endregion
由于开启协程只能在主线程中开启,所以当必须创建一个GameObject再挂载脚本。使用单例的创建模式,在Instance是对GameObject进行创建,当截屏完成是,对GameObject进行删除(你也可以在3-5秒后再删除,免于频繁截屏创建销毁的开销)
- public class CaptureScreenTool : MonoBehaviour {
- private static CaptureScreenTool instance = null;
- private bool isRunning = false;//是否正在保存,防止开启多个协程多次截屏
- private Delegate callBack = null;//设置外部回调
- private ImgType curType = ImgType.PNG;//设置保存格式
- private const string saveDirectoryName = "captureData";//文件夹
- public enum ImgType
- {
- PNG,
- JPG
- }
- public static CaptureScreenTool Instance
- {
- get
- {
- if (instance == null)
- {
- //初始化创建GameObject物品,挂载脚步,这样才能开启协程
- GameObject temp = new GameObject();
- instance = temp.AddComponent<CaptureScreenTool>();
- }
- return instance;
- }
- }
- private IEnumerator captureScreenPic(Delegate callBack)
- {
- yield return new WaitForEndOfFrame();//等待帧缓存结束
- int width=Screen.width;
- int height=Screen.height;
- //创建一个Texture2D纹理,可查看手册
- Texture2D pic = new Texture2D(width, height, TextureFormat.RGB24, false);
- pic.ReadPixels(new Rect(0, 0, width, height), 0, 0, true);
- byte[] imageBytes = null;
- string imageName = null;
- switch (curType)
- {
- case ImgType.PNG:
- imageName = System.DateTime.Now.ToFileTime().ToString() + ".png";//根据时间设置文件名,防止重复,也可反推日期
- imageBytes = pic.EncodeToPNG();
- break;
- case ImgType.JPG:
- imageName = System.DateTime.Now.ToFileTime().ToString() + ".jpg";
- imageBytes = pic.EncodeToJPG();
- break;
- }
- if (imageBytes == null || imageName == null)
- StopCoroutine(captureScreenPic(callBack));
- string path=Application.persistentDataPath+"/"+saveDirectoryName+"/"+imageName;
- //保存文件操作
- if (FIleMag.saveBytes(path, imageBytes))
- {
- if (callBack != null)
- callBack.DynamicInvoke(path);//回调外部方法,返回路径,可用于获取文件路径进行分享什么的操作
- }
- //销毁操作
- callBack = null;
- Destroy(gameObject);
- instance = null;
- isRunning = false;
- }
- //外部调用方法,如CaptureScreenTool.Instance.saveScreenPic((Action<string>)save);
- public void saveScreenPic(Delegate callback, ImgType type = ImgType.PNG)
- {
- if (isRunning)
- return;
- Debug.Log("saveScreenPic");
- curType = type;
- StartCoroutine(captureScreenPic(callback));
- }
- }
此方法只对整个屏幕进行截屏,不能对单个摄像机层次剔除进行分别的截屏