You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity RenderTexture读取越界及截图显示异常问题求助

Unity截取小地图RenderTexture报错及全屏显示解决方案

问题分析

你遇到的Attempting to ReadPixels outside of RenderTexture bounds错误,根源是混淆了屏幕坐标和RenderTexture内部坐标:你用ViewportToScreenPoint获取的是小地图在屏幕上的位置(屏幕坐标),但读取RenderTexture像素时需要用它自身的内部坐标,两者范围完全不匹配,导致读取区域超出RenderTexture的768×432边界。

另外你提到设置RoI为(0,0,targetTextureWidth,targetTextureHeight)后截图不符合预期,是因为之前通过屏幕坐标计算的targetTextureWidth/Height可能存在误差,且没有正确处理全屏显示的绘制逻辑。

修正方案

核心思路

  1. 直接为turretCamera创建固定尺寸(768×432)的RenderTexture,避免通过屏幕坐标计算带来的误差;
  2. 读取RenderTexture像素时,直接读取其完整区域(内部坐标从(0,0)到自身宽高);
  3. 全屏显示时,将截取的纹理绘制到整个屏幕区域。

修正后代码

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 03:44:54