简介

介于照抄网上之前的截图教程,然后在实际应用过程中出现了一些小小的问题,修正了一下下,特此分享一下

PS:代码在后面

原理

原理很简单,就是将一个相机的内容渲染到一个贴图上,然后将贴图保存为图片

坑s

1.摄像机截图发现内容不全(比如3D模型丢失)

摄像机渲染的对象是一个RenderTexture,然后RenderTexture的构造函数大体上是这样的:

RenderTexture(int width, int height, int depth, RenderTextureFormat format, RenderTextureReadWrite readWrite);

最后两个参数就不解释了,width 和 height就是宽和高的分辨率,也不用解释,比较坑的是depth

官方的解释是:Number of bits in depth buffer (0, 16 or 24). Note that only 24 bit depth has stencil buffer

大概意思就是这个是位图深度,只能是0、16、24三个参数,然后如果你的深度不够的话,就会出现部分模型不显示,具体原因我也不知道,只能臆测是unity渲染是把不同layer的物体渲染到不同的深度上吧

然后由于之前抄的教程构造函数是这样写的:new RenderTexture((int)rect.width, (int)rect.height, 0),导致截图内容只有UI层,其他层一概不显示

最终解决方案是:new RenderTexture((int)rect.width, (int)rect.height, 24);把最后一个参数改成24就好了。

2.截屏无法分享(文件无法访问)

其实这个是自己的问题,在传入路劲的时候使用了Application.dataPath.......

这个路径返回的是asset下的路劲,无法进行读写,导致在分享的时候操作失败(估计也没有写入成功,因为按照原理这个路径应该是打包进入apk里面的)

解决方案很简单,换成Application.persistentDataPath就可以了

3.截屏卡顿

这个问题捣鼓了很久,至少两个小时以上.......

先是把截屏弄成了协程,然后分别放到了独立帧,然后把文件IO改成了buffer的,最后发现还是卡

然后辗转反侧,反侧辗转,突然发现手机上的截图文件巨大无比(手机分辨率太高了.......截图的时候是按照屏幕分辨率来的)

然后就得出了以下解决方案:

float tempScale = SCREEN_SHOT_WIDTH / Screen.width;
StartCoroutine(CaptureCamera(captureCamera, new Rect(0, 0, Screen.width * tempScale, Screen.height * tempScale), mPicturePath));

应该都看的懂吧,就是先指定一个分辨率,然后把截图尺寸缩放一下,然后截图,这样就可以流畅的截图了

4.截图无法截取UGUI的元素

目前这个问题的解决方案依然不是很完善,不知道后续会不会变好

目前有两个解决方案:

1.将UGUI设置为word Space 模式,这样UI元素就是3D场景咯,就可以直接截图了,但是这样的弊端是UI需要自己去让他跟随摄像机(其实解决也很简单,扔到摄像机下面就行了)

2.重新弄一个3D TEXT,因为截屏的时候一般都是纯的游戏场景加部分特殊UI,所以可以只在截图层加一个特殊的3D文字或者直接扔一张图片也可以,这样就不用改动原来的UI了

代码

代码比较拙计,但是好歹能用,先这样吧...... 下班咯.......

using UnityEngine;
using System.Collections;
using System.IO; public class ScreenShotUtil : MonoBehaviour
{ private const float SCREEN_SHOT_WIDTH = 400; private static ScreenShotUtil mInstance; private static string mPicturePath; public Camera captureCamera; void Awake()
{
mInstance = this; // 获取对应平台的可访问路径
mPicturePath = Application.persistentDataPath + "/screenshot.png";
} public static void Shot()
{
mInstance.TackCapture();
} /// <summary>
/// 截屏操作
/// </summary>
private void TackCapture()
{
float tempScale = SCREEN_SHOT_WIDTH / Screen.width;
StartCoroutine(CaptureCamera(captureCamera, new Rect(0, 0, Screen.width * tempScale, Screen.height * tempScale), mPicturePath));
} IEnumerator CaptureCamera(Camera camera, Rect rect, string imgPath)
{
yield return new WaitForEndOfFrame();
// 创建一个RenderTexture对象
RenderTexture rt = new RenderTexture((int)rect.width, (int)rect.height, 24);
// 临时设置相关相机的targetTexture为rt, 并手动渲染相关相机
camera.targetTexture = rt;
camera.Render();
yield return new WaitForEndOfFrame(); // 激活这个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();
// 重置相关参数,以使用camera继续在屏幕上显示
camera.targetTexture = null;
RenderTexture.active = null; // JC: added to avoid errors
GameObject.Destroy(rt);
yield return new WaitForEndOfFrame(); // 最后将这些纹理数据,成一个png图片文件
byte[] bytes = screenShot.EncodeToPNG();
string filename = imgPath;
File.WriteAllBytes(filename, bytes); SDKUtils.ShowToast(filename);
} public static string GetPicturePath()
{
return mPicturePath;
} }

总结

其实没啥总结的,只是想说unity自带的截屏功能太寒掺咯~~~~

Unity通过指定摄像机截屏的更多相关文章

  1. 纯C#实现屏幕指定区域截屏

    以前在别的地方见过一个通过调用系统API实现屏幕截图的例子,从内心来说我不太喜欢在C#代码中出现这种情况,现在什么都讲“和谐”,我觉得这种做法就是破坏了我们的“和谐”代码,呵呵,开玩笑,有的时候,不通 ...

  2. C#实现屏幕指定区域截屏

    //string Opath = @"C:/Picture";            //if (Opath.Substring(Opath.Length - 1, 1) != @ ...

  3. unity中编辑器直接截屏代码

    using UnityEngine; using System.Collections; using System.Windows.Forms; public class screenshots : ...

  4. javascript实现当前页面截屏

    javascript实现当前页面截屏 一.前言 有客户要求能对用户当前页面进行指定区域截屏,类似qq截屏的实现效果.比如用户在处理工作的时候,将当前页面录入后的一些信息进行截图下载保存.但又不能安装任 ...

  5. unity之截屏功能

    1.全屏截图 方法一:在unity的API中,unity给我们提供了一个现成的API  :  Application.CaptureScreenshot(imagename). 但是这个API虽然简单 ...

  6. 关于Unity中GrabPass截屏的使用和Shader的组织优化

    GrabPass截屏 可以用来截屏,截屏后把纹理传给下一个通道使用. 1:使用抓屏通道, GrabPass {} 或 GrabPass { “ 纹理名称”}; 使用GrabPass {}后,可以用_G ...

  7. Unity三种截屏方法(非自带API)

    者利用了三种表现形式: 1,选择截图路径的方法 2,直接截取截屏的方法 3,截取鼠标圈选区域. 上代码,: 第一种是调用.net的类库,需要引用System.Windows.Forms.dll,在As ...

  8. unity 截屏总结

    转载与https://www.cnblogs.com/MissLi/p/8005342.html 1.针对指定的相机进行截屏 此中方式要添加yield return waitfortheEndofFr ...

  9. 一个类实现Java截屏并保存到指定文件夹

    不知小伙伴们有没有遇到过使用java来截屏的需求,截屏后保存到指定的目录,在桌面上没有任何体现,完全不知道已经被截屏了.至于截屏后怎么做,可能有的老铁只是好奇想知道某人在干啥?也有的老铁可能想进行文字 ...

随机推荐

  1. [bzoj1820][JSOI2010][Express Service 快递服务] (动态规划)

    Description 「飞奔」快递公司成立之后,已经分别与市内许多中小企业公司签订邮件收送服务契约.由于有些公司是在同一栋大楼内,所以「飞奔」公司收件的地点(收件点)最多只有m点 (1, 2, …, ...

  2. Java Web学习总结(29)——Java Web中的Filter和Interceptor比较

    1. 背景 在设计web应用的时候,用户登录/注册是必不可少的功能,对用户登录信息进行验证的方法也是多种多样,大致可以认为如下模式:前端验证+后台验证.根据笔者的经验,一般会在前端进行一些例如是否输入 ...

  3. Java Syntax Specification

    Java Syntax Specification Programs <compilation unit> ::= <package declaration>? <imp ...

  4. 九度oj 题目1473:二进制数

    题目描述: 大家都知道,数据在计算机里中存储是以二进制的形式存储的. 有一天,小明学了C语言之后,他想知道一个类型为unsigned int 类型的数字,存储在计算机中的二进制串是什么样子的. 你能帮 ...

  5. noip模拟赛 算

    [问题背景]zhx 帮他妹子做数学题.[问题描述]求: 如 N=3, M=3, 这个值为 1^1+1^2+1^3+2^1+2^2+2^3+3^1+3^2+3^3=56. [输入格式]仅一行, 包含两个 ...

  6. noip模拟赛 圆桌游戏

    [问题描述] 有一种圆桌游戏是这样进行的:n个人围着圆桌坐成一圈,按顺时针顺序依次标号为1号至n号.对1<i<n的i来说,i号的左边是i+1号,右边是i-1号.1号的右边是n号,n号的左边 ...

  7. apt-get使用指南

    最近频繁使用apt-cache show(查看软件包详细信息)与apt-cache search(搜寻具体软件包确切名称)命令,深感方便与功能强大.现将一些apt-get相关命令做一个简单的收集: a ...

  8. 你的ExcelUtil简单、高效、易扩展吗

    你的ExcelUtil简单.高效.易扩展吗 Author: Dorae Date: 2018年10月23日12:30:15 转载请注明出处 一.背景 最近接到了和Excel导出相关的需求,但是: 项目 ...

  9. Performance Tunning - OCP

    This artical is forcused on Oracle 11g Release 2.  It is an summary from the OCP documentation. The ...

  10. CentOS 7: 设置时区和时间

    查看当前时区和时间 $ date $ ls -l /etc/localtime 查看所有可用时区 $ timedatectl list-timezones | grep Asia 设置时区 $ tim ...