news 2026/10/23 4:55:13

【Unity开发】局部区域截图功能实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【Unity开发】局部区域截图功能实现


🐾 个人主页 🐾
阿松爱睡觉,横竖醒不来
🏅你可以不屠龙,但不能不磨剑🗡

文章目录

  • 一、前言
  • 二、思路
    • (一)直接开一张小的 RenderTexture?不行
    • (二)整屏渲染,读取的时候挑地方
  • 三、完整代码
  • 四、代码讲解
    • (一)中间区域的坐标怎么算
    • (二)ReadPixels 只读一块
    • (三)收尾工作
  • 五、注意事项
  • 六、结语

一、前言

上一篇文章讲的长截图,有长截图就有短截图,或者区域截图,这篇文章就是说的区域截图,而且比长截图简单得多——不用滚动、不用拼接、不用算零头,渲染还是完整渲染一遍,只是读取像素的时候指定一个区域就行。比如只截游戏画面中间 500*400 的区域,把边缘的 UI 完美避开,用的就是这一招。

那么话不多说,直接开始今天的内容吧!

二、思路

(一)直接开一张小的 RenderTexture?不行

肯定有同学会想:截 500400 的区域,那我把 RenderTexture 直接开成 500400 不就行了?

不行👇👇👇。相机渲染到一张小的 RenderTexture 上,是把整个视野缩放着塞进去,相当于给画面打了个缩小镜头,并不是裁剪。不信的话可以自己试,截出来该有的东西一样不少,只是全都变小了。

所以裁剪这件事,只能在读像素这一步做。

(二)整屏渲染,读取的时候挑地方

正解分两步:

  1. RenderTexture 该开多大还开多大,和屏幕保持一致,相机完整渲染一遍;
  2. ReadPixels的时候传一个Rect,只读中间那块区域的像素,读出来的纹理就只有这么大。

一句话概括:渲染要完整,读取挑地方。下面直接上代码。

三、完整代码

usingSystem.IO;usingUnityEngine;publicclassShotPartScreen:MonoBehaviour{publicCameracamera1;// 用来截图的相机publicGameObjectbutton1;// 截图期间要藏起来的按钮/// <summary>/// 截取屏幕中间 500*400 的区域/// </summary>publicvoidStartShotPart(){button1.SetActive(false);StartCoroutine(ShotPartTexture());}privateIEnumeratorShotPartTexture(){// 和上一期长截图一个道理:等到帧结束,画面渲染完了再动手yieldreturnnewWaitForEndOfFrame();// 创建一张和屏幕一样大的 RenderTexture,作为相机的渲染目标RenderTexturerenderTexture=newRenderTexture(Screen.width,Screen.height,24);camera1.targetTexture=renderTexture;camera1.Render();// 计算屏幕中间 500*400 区域的坐标(注意坐标原点在左下角)intcenterX=Screen.width/2;intcenterY=Screen.height/2;inthalfWidth=250;// 500的一半inthalfHeight=200;// 400的一半RectmiddleRect=newRect(centerX-halfWidth,centerY-halfHeight,500,400);// 把 RenderTexture 设为激活状态,然后只读取中间区域的像素RenderTexture.active=renderTexture;Texture2Dtexture2D=newTexture2D(500,400,TextureFormat.RGB24,false);texture2D.ReadPixels(middleRect,0,0);texture2D.Apply();// 收尾:激活状态和渲染目标都还原,RenderTexture 该释放就释放RenderTexture.active=null;camera1.targetTexture=null;renderTexture.Release();// 保存成 PNGstringpath=Path.Combine(Application.dataPath,"SavedScreen.png");File.WriteAllBytes(path,texture2D.EncodeToPNG());Debug.Log($"xiao=====:{path}");// 把藏起来的按钮恢复回去button1.SetActive(true);}}

四、代码讲解

(一)中间区域的坐标怎么算

思路很直白:屏幕中心点减去半个宽度和高度,拿到矩形的左下角。

intcenterX=Screen.width/2;intcenterY=Screen.height/2;inthalfWidth=250;// 500的一半inthalfHeight=200;// 400的一半RectmiddleRect=newRect(centerX-halfWidth,centerY-halfHeight,500,400);

这里有一个坑要特别注意:屏幕和 RenderTexture 的坐标原点在左下角,y 轴向上。不少同学习惯性地按左上角为原点去算,算出来的位置直接就偏了。自检方法很简单:算出来的 x、y 应该都是正数,且x + 500、y + 400不超过屏幕宽高,那就对了。

(二)ReadPixels 只读一块

ReadPixels的三个参数:从哪读、贴到哪、贴多大区域。

texture2D.ReadPixels(middleRect,0,0);

意思就是:从当前激活的 RenderTexture 里middleRect这块区域读像素,贴到纹理的(0, 0)处。纹理本身开的是 500*400,和middleRect的尺寸一一对应,刚好贴满。

这里要强调原话:ReadPixels 里的坐标和尺寸是相对于 RenderTexture 的,不是相对于屏幕的。本例中 RenderTexture 和屏幕一样大,所以直接用屏幕坐标没问题;如果你的 RenderTexture 是别的尺寸(比如为了性能开了一半分辨率),坐标就要按比例换算,不能直接套屏幕坐标。

另外,Texture2D 的尺寸必须和 Rect 的尺寸一致,不一致 ReadPixels 会直接给你脸色看(读取异常或者花屏),这个没有商量。

(三)收尾工作

截图这活,重点都在收尾,三件事漏一件就出事:

  1. RenderTexture.active = null。不清掉的话,后面所有正常渲染都会写到这张 RenderTexture 上,游戏画面直接消失,这个坑踩过的人都懂。
  2. renderTexture.Release()。RenderTexture 占的是 GPU 内存,不释放就一直攒着,截得越多爆得越快。
  3. button1.SetActive(true)。截图前把按钮藏了,截完记得放出来,不然用户对着空气点半天。

哦对了,原来代码里保存路径是这么写的:

File.WriteAllBytes(Application.dataPath+" /SavedScreen.png",bytes);

引号里面多打了一个空格,存出来的文件名前面带空格,路径看着没毛病,找文件的时候能给你找懵。所以优化版换成了Path.Combine,分隔符也不用自己操心了:

stringpath=Path.Combine(Application.dataPath,"SavedScreen.png");

五、注意事项

  1. 坐标原点在左下角,算中间区域的时候别按左上角算,这是最常见的错。
  2. Texture2D 尺寸必须和 Rect 尺寸一致,都是 500400,不能一个 500400 一个 600*400。
  3. 截取区域别超出屏幕范围。现在机型分辨率五花八门,小屏机上 500*400 也可能贴边,需要的话按屏幕尺寸做个 clamp,把宽高夹一下。
  4. RenderTexture 用完必须释放,active 状态必须还原,上面说过了,这里再啰嗦一遍。
  5. 路径按平台区分。Editor 里Application.dataPath指向 Assets 目录,真机上更建议用Application.persistentDataPath。
  6. 老生常谈:如果 UI 是 Screen Space - Overlay,相机渲染抓不到 UI,得换成等帧结束直接读屏幕后备缓冲的思路,这个在长截图那期说过,这里不重复了。

六、结语

局部截图比长截图简单得多——不用滚、不用拼,RenderTexture 完整渲染一遍,ReadPixels 指定个 Rect 就完事了。真正的坑全在细节里:坐标原点、尺寸匹配、释放还原,这三件事忘了任何一件,轻则截图截歪了,重则画面全黑。

建议大家照着代码自己敲一遍,顺手把 500*400 改成别的尺寸试试,看看截出来的位置对不对。

如果在实践的过程中遇到什么问题,欢迎在评论区留言,我看到的话会及时回复。这期的内容就到这里,下期见,拜拜!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/23 4:53:46

不用媒体创建工具,也能做出 Windows 11 启动 U 盘吗?能——方法在这儿

答案是能——你完全可以在不使用微软媒体创建工具(Media Creation Tool)的情况下,制作 Windows 11 启动 U 盘。事实上,很多 IT 从业者和技术爱好者更偏爱替代方法,因为它们更可控、更灵活,往往还比官方工具更快。 虽然微软官方推荐用媒体创建工具,但它也有不少缺点,而…

作者头像 李华
网站建设 2026/10/23 4:52:43

ESP-Drone 完整上手指南:用 ESP32-S2 做一架手机可控的四旋翼

ESP-Drone 完整上手指南&#xff1a;用 ESP32-S2 做一架手机可控的四旋翼 【免费下载链接】esp-drone Mini Drone/Quadcopter Firmware for ESP32 and ESP32-S Series SoCs. 项目地址: https://gitcode.com/GitHub_Trending/es/esp-drone 你有没有想过&#xff0c;一台 …

作者头像 李华
网站建设 2026/10/23 4:51:40

Graph-Engineering-第1章第4节-临界点-为什么是2026

为什么是2026&#xff1f;Graph Engineering爆发的五大临界点 Graph Engineering 系列课程 第1章第4节 临界点分析 这是 127 篇 Graph Engineering 系统课程的第四篇。前几节我们聊了 Peter Steinberger 那条推文、图的核心概念、以及 172.5 亿美元的市场全景。这一节&#x…

作者头像 李华