一、截取整个屏幕(含 UI)
原理:
在 URP 中,相机不能依赖 Camera.Render() 强制渲染完整内容,因此截取单个相机的正确方式,是让该相机将其输出写入一个自定义 RenderTexture,然后再从这个 RenderTexture 中通过 ReadPixels() 读取像素。由于此时 RenderTexture.active 被设置为该 RT,ReadPixels() 读取的就是该相机的独立渲染结果,不会包含其他相机,也不会包含 Overlay 模式的 UI,因此非常适合“只截主相机”、“不带 UI 的游戏画面”,或“离屏渲染”。
步骤:
- 创建一个 RenderTexture(匹配你需要的分辨率)。
- 将主相机的
targetTexture设置为该 RenderTexture。 - 在本帧末尾(
WaitForEndOfFrame)调用cam.Render()或依赖 URP 自动渲染。 - 设置
RenderTexture.active = rt。 - 调用
ReadPixels()将 RenderTexture 读入 Texture2D。 - 调用
Apply()然后恢复:cam.targetTexture = null; RenderTexture.active = null;。
7.(可选)保存为图片。
实现:
public IEnumerator CaptureFullScreen()
{
yield return new WaitForEndOfFrame(); // 等待 URP 整帧绘制完成
int width = Screen.width;
int height = Screen.height;
Texture2D tex = new Texture2D(width, height, TextureFormat.RGB24, false);
tex.ReadPixels(new Rect(0, 0, width, height), 0, 0); // 从 FrameBuffer 读
tex.Apply();
// 保存
string path = Application.dataPath + "/../Screenshot.png";
System.IO.File.WriteAllBytes(path, tex.EncodeToPNG());
Debug.Log("Full screen screenshot saved: " + path);
}
二、截主相机画面(单独相机 RenderTexture 截图)
原理:
在 URP 中,所有相机的颜色输出、后处理效果以及 UGUI 的最终渲染结果,都会被写入到屏幕的 Back Buffer(FrameBuffer)中。在整帧渲染结束后,只要不修改 RenderTexture.active,Unity 默认将 FrameBuffer 当作当前的 Active RenderTarget。此时调用 Texture2D.ReadPixels(),读取的就是这一帧屏幕最终成品的像素数据,因此可以完整保留所有 UI、所有 Camera 的叠加画面。为了确保 FrameBuffer 内容已渲染完毕,必须在 WaitForEndOfFrame() 之后执行。
步骤:
yield return new WaitForEndOfFrame()等待 URP 完成整帧渲染。- 不设置任何 RenderTexture(保持
RenderTexture.active = null)。 - 创建一个 Texture2D(RGB24 或 RGBA32)。
- 调用
ReadPixels(new Rect(0,0,w,h), 0,0)直接从 FrameBuffer 读取像素。 - 调用
Apply()生成最终纹理。
6.(可选)编码为 PNG/JPG 保存。
实现:
public IEnumerator CaptureMainCamera(Camera cam, int width, int height)
{
yield return new WaitForEndOfFrame();
RenderTexture rt = new RenderTexture(width, height, 24);
cam.targetTexture = rt;
// 在 URP 中,等待到这一帧结束,Camera.Render() 不强制必须
cam.Render();
RenderTexture.active = rt;
Texture2D tex = new Texture2D(width, height, TextureFormat.RGB24, false);
tex.ReadPixels(new Rect(0, 0, width, height), 0, 0);
tex.Apply();
cam.targetTexture = null;
RenderTexture.active = null;
// 保存到文件
string path = Application.dataPath + "/../MainCamera.png";
System.IO.File.WriteAllBytes(path, tex.EncodeToPNG());
Debug.Log("Main camera screenshot saved: " + path);
}
如果要性能更好(避免 ReadPixels 卡顿)
Unity2021 支持 AsyncGPUReadback,不会卡主线程
AsyncGPUReadback.Request(rt, 0, TextureFormat.RGBA32, OnReadbackComplete);
void OnReadbackComplete(AsyncGPUReadbackRequest req)
{
if (req.hasError)
{
Debug.LogError("Readback Error!");
return;
}
var tex = new Texture2D(width, height, TextureFormat.RGBA32, false);
tex.LoadRawTextureData(req.GetData<byte>());
tex.Apply();
}
16万+

被折叠的 条评论
为什么被折叠?



