Unity局部截图、全屏截图、带UI截图方法总结汇总

根据项目的需求,在unity中涉及的截图主要有全屏截图、局部截图、带UI截图等形式。下面很具这几种形式对在unity中截图的方法进行总结。

1. 局部截图

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
public RectTransform UIRect;

void Update () {
if (Input.GetKeyDown(KeyCode.Space)) {
string fileName = Application.dataPath + "/StreamingAssets/" + "123.png";
IEnumerator coroutine = CaptureByUI(UIRect, fileName);
StartCoroutine(coroutine);
}
}

public IEnumerator CaptureByUI(RectTransform UIRect, string mFileName) {
//等待帧画面渲染结束
yield return new WaitForEndOfFrame();

int width = (int)(UIRect.rect.width );
int height = (int)(UIRect.rect.height);

Texture2D tex = new Texture2D(width, height, TextureFormat.RGB24, false);

//左下角为原点(0, 0)
float leftBtmX = UIRect.transform.position.x + UIRect.rect.xMin ;
float leftBtmY = UIRect.transform.position.y + UIRect.rect.yMin ;

//从屏幕读取像素, leftBtmX/leftBtnY 是读取的初始位置,width、height是读取像素的宽度和高度
tex.ReadPixels(new Rect(leftBtmX, leftBtmY, width, height), 0, 0);
//执行读取操作
tex.Apply();
byte[] bytes = tex.EncodeToPNG();
//保存
System.IO.File.WriteAllBytes(mFileName, bytes);
}

在Canvas下新建一个Image,截去这个Image的所在区域,按下空格即可截取Image所在的区域。

2. 全屏截图

a. unity内置了一种非常简单的截图方法,截取的某一帧的画面。

1
2
3
public void CaptureScreenByUnity(string fileName) {
UnityEngine.ScreenCapture.CaptureScreenshot(fileName);
}

b. 利用局部截图里面的方法,设置一个覆盖全屏的UI组件,也可实现全屏截图。

c. 利用OnPostRender方法进行截图, OnPostRender是Camera类下的方法,所以要想执行该方法,脚本必须挂载在相机下面。截取的画面是相机画面,如果Canvas的RenderMode为默认的ScreenSpace-Overlay,截图是不带UI元素的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//该脚本必须附加在Camera相机组件所在物体对象上OnPostRender方法才会执行
//当camera完成场景的渲染时会被激活执行
private void OnPostRender() {
if (grab) {
//创建一个设置好的屏幕宽度和高度
//Screen.width 和 Screen.height 为在game窗口设置的宽度和高度
Texture2D texture = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false);
//Read the pixels in the Rect starting at 0,0 and ending at the screen's width and height
texture.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0, false);
texture.Apply();
byte[] bytes = texture.EncodeToPNG();
//保存
System.IO.File.WriteAllBytes(fileName, bytes);
grab = false;
}
}

3. 带UI截图(利用RenderTexture截图)

需要新建一个Canvas,RenderMode设置为ScreenSpace-Camera,把需要出现在截图当中的元素放在该Canvas下面。然后在新建一个专门进行截图的Camera。设置该Camera为Canvas的渲染相机RenderCamera。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public void CaptureScreenByRT(Camera camera, string fileName) {
Rect rect = new Rect(0, 0, 1920, 1080);
// 创建一个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);
// 注:这个时候,它是从RenderTexture.active中读取像素
screenShot.ReadPixels(rect, 0, 0);
screenShot.Apply();
// 重置相关参数,以使用camera继续在屏幕上显示
camera.targetTexture = null;
RenderTexture.active = null;
GameObject.Destroy(rt);
// 最后将这些纹理数据,成一个png图片文件
byte[] bytes = screenShot.EncodeToPNG();

System.IO.File.WriteAllBytes(fileName, bytes);
}

最后提示,使用局部截图和全屏截图中的方法texture.ReadPixels方法容易出现读取像素超出边界的错误,截图变成纯灰色图片。错误信息:[d3d11] attempting to ReadPixels outside of RenderTexture bounds!

如下所示:

1
[d3d11] attempting to ReadPixels outside of RenderTexture bounds! Reading (0, 0, 512, 512) from (511, 909)

遇到此种错误,解决办法建议使用第三种利用Camera和RenderTexture进行截图。此种方法想截取多大区域,多大的图片就能截取多大的图片。

本文来自:https://blog.csdn.net/u012730137/article/details/80150495