Unity:如何在执行Texture2D.ReadPixels前缩小Render Texture获取全画面截图
解决Unity Camera截图缩放后仅显示局部的问题
你的问题根源在于直接修改ReadPixels的读取尺寸时,只是从屏幕截取了对应大小的局部区域,而非对整个画面进行缩放。针对高频(30ms一次)低质量截图的需求,推荐两种高效的实现方式:
方法一:CPU端缩放Texture2D(适合简单场景)
先读取全屏画面,再通过GPU拷贝完成纹理缩放,完整保留整个视野:
public class CameraRenderToImage : MonoBehaviour { // 目标截图尺寸,可按需调整 public int targetWidth = 320; public int targetHeight = 240; private Texture2D fullScreenTex; private Texture2D scaledTex; void Start() { TimeStamp.SetStart(); Camera.onPostRender += OnPostRenderCallback; // 提前创建纹理,避免频繁GC fullScreenTex = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false); scaledTex = new Texture2D(targetWidth, targetHeight, TextureFormat.RGB24, false); } void OnPostRenderCallback(Camera cam) { if (TimeStamp.HasMoreThanThisEllapsed(30)) { TimeStamp.SetStart(); // 读取全屏画面 fullScreenTex.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0); fullScreenTex.Apply(); // 缩放到目标尺寸(GPU层面拷贝,性能优于CPU缩放) scaledTex.Resize(targetWidth, targetHeight); Graphics.CopyTexture(fullScreenTex, scaledTex); scaledTex.Apply(); // 保存缩放后的纹理 byte[] bytes = scaledTex.EncodeToPNG(); System.IO.File.WriteAllBytes("check_me_out.png", bytes); TimeStamp.Tok("Encode to PNG and Save"); } } void OnDestroy() { Camera.onPostRender -= OnPostRenderCallback; // 销毁纹理释放资源 Destroy(fullScreenTex); Destroy(scaledTex); } }
方法二:GPU端通过RenderTexture下采样(性能更优,适合高频捕获)
让Camera直接渲染到小尺寸RenderTexture,由GPU完成画面缩放,避免CPU端额外开销,更适合30ms间隔的高频截图场景:
public class CameraRenderToImage : MonoBehaviour { public int targetWidth = 320; public int targetHeight = 240; private RenderTexture renderTex; private Texture2D outputTex; void Start() { TimeStamp.SetStart(); Camera.onPostRender += OnPostRenderCallback; // 创建小尺寸RenderTexture,设置过滤模式优化缩放效果 renderTex = new RenderTexture(targetWidth, targetHeight, 24); renderTex.filterMode = FilterMode.Bilinear; outputTex = new Texture2D(targetWidth, targetHeight, TextureFormat.RGB24, false); // 将当前Camera的渲染目标切换为小尺寸RenderTexture GetComponent<Camera>().targetTexture = renderTex; } void OnPostRenderCallback(Camera cam) { if (TimeStamp.HasMoreThanThisEllapsed(30)) { TimeStamp.SetStart(); // 激活RenderTexture并读取像素 RenderTexture.active = renderTex; outputTex.ReadPixels(new Rect(0, 0, targetWidth, targetHeight), 0, 0); outputTex.Apply(); RenderTexture.active = null; // 保存处理后的纹理 byte[] bytes = outputTex.EncodeToPNG(); System.IO.File.WriteAllBytes("check_me_out.png", bytes); TimeStamp.Tok("Encode to PNG and Save"); } } void OnDestroy() { Camera.onPostRender -= OnPostRenderCallback; // 恢复Camera默认渲染目标 GetComponent<Camera>().targetTexture = null; Destroy(renderTex); Destroy(outputTex); } }
关键提示
- 优先选择方法二,GPU缩放性能远高于CPU操作,能有效降低高频截图带来的性能压力
- 提前创建并复用纹理对象,避免每帧创建新纹理导致的GC抖动
- 可通过调整
FilterMode控制缩放质量:FilterMode.Point适合像素风格画面,FilterMode.Bilinear适合平滑过渡的场景
内容的提问来源于stack exchange,提问作者aarelovich
相关产品推荐
相关产品推荐

