Unity RenderTexture读取越界及截图显示异常问题求助
Unity截取小地图RenderTexture报错及全屏显示解决方案
问题分析
你遇到的Attempting to ReadPixels outside of RenderTexture bounds错误,根源是混淆了屏幕坐标和RenderTexture内部坐标:你用ViewportToScreenPoint获取的是小地图在屏幕上的位置(屏幕坐标),但读取RenderTexture像素时需要用它自身的内部坐标,两者范围完全不匹配,导致读取区域超出RenderTexture的768×432边界。
另外你提到设置RoI为(0,0,targetTextureWidth,targetTextureHeight)后截图不符合预期,是因为之前通过屏幕坐标计算的targetTextureWidth/Height可能存在误差,且没有正确处理全屏显示的绘制逻辑。
修正方案
核心思路
- 直接为turretCamera创建固定尺寸(768×432)的RenderTexture,避免通过屏幕坐标计算带来的误差;
- 读取RenderTexture像素时,直接读取其完整区域(内部坐标从(0,0)到自身宽高);
- 全屏显示时,将截取的纹理绘制到整个屏幕区域。
修正后代码
using UnityEngine; // 请确保引入Model和Worker相关命名空间 public class MinimapCapture : MonoBehaviour { public Camera turretCamera; public ModelAsset modelAsset; private Worker worker; private RenderTexture renderTexture; private RenderTexture tmpRenderTexture; private Texture2D minimapTexture; // 小地图固定尺寸 private const int MINIMAP_WIDTH = 768; private const int MINIMAP_HEIGHT = 432; void Start() { // 初始化模型与Worker Model model = ModelLoader.Load(modelAsset); worker = WorkerFactory.CreateWorker(WorkerFactory.Type.ComputePrecompiled, model); // 创建匹配小地图尺寸的RenderTexture renderTexture = new RenderTexture(MINIMAP_WIDTH, MINIMAP_HEIGHT, 24); // 保存原渲染目标,退出时恢复 tmpRenderTexture = turretCamera.targetTexture; turretCamera.targetTexture = renderTexture; } // 每帧末尾更新截图,确保turretCamera已完成渲染 private void LateUpdate() { UpdateMinimapScreenshot(); } private void UpdateMinimapScreenshot() { if (renderTexture == null) return; // 初始化或更新Texture2D尺寸 if (minimapTexture == null || minimapTexture.width != renderTexture.width || minimapTexture.height != renderTexture.height) { minimapTexture = new Texture2D(renderTexture.width, renderTexture.height, TextureFormat.RGB24, false); } // 读取RenderTexture完整像素 RenderTexture.active = renderTexture; minimapTexture.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0); minimapTexture.Apply(); RenderTexture.active = null; } private void OnGUI() { if (minimapTexture == null) return; // 全屏绘制小地图纹理 GUI.DrawTexture(new Rect(0, 0, Screen.width, Screen.height), minimapTexture); } // 清理资源,避免内存泄漏 private void OnDestroy() { if (turretCamera != null && tmpRenderTexture != null) { turretCamera.targetTexture = tmpRenderTexture; } if (renderTexture != null) { renderTexture.Release(); Destroy(renderTexture); } if (minimapTexture != null) { Destroy(minimapTexture); } worker?.Dispose(); } }
关键说明
- RenderTexture坐标逻辑:Unity纹理的原点在左下角,所以读取完整区域用
new Rect(0, 0, renderTexture.width, renderTexture.height)即可,无需涉及屏幕坐标; - 渲染时机:用
LateUpdate更新截图,确保turretCamera在当前帧已经完成渲染,避免截取到空白或旧画面; - 资源清理:在
OnDestroy中恢复原渲染目标、释放RenderTexture和Texture2D,防止内存泄漏。
内容的提问来源于stack exchange,提问作者Alfonso
相关产品推荐
相关产品推荐

