简单游戏截图_可控截取内容2

news/2024/11/24 14:06:45/

一个需求

我需要在场景中截取不同层级的截图(如只截模型或只截UI或只截外部相加看到的画面 或全都截或和Shader配合呈现人眼夜视仪热成像的画面切换)
将截图排到列表中,在场景UI中展示出来

如何做

  1. 相机要能够看到不同的画面
  2. 将当前帧画面存储下来
  3. 将存储的画面展示出来
知识点代码
https://developer.unity.cn/projects/64ca2cbbedbc2a00187ba6d6
下面继续

做一个练习 截屏细节 轮廓+UI 全部三张图分别展示出来

  1. 首先给游戏对象分好类
  1. 简单设计一下UI,截图功能会在此操作,截图会在此展示
三个相加分别是Main 场景的主相机,DesktopUI界面UI专门展示的相机, CamTexture专门用来截图操作的相机平时不打开,只在截图时候打开截这个相机渲染的画面
  1. CamTexture想要渲染不同的画面就要对他进行不同的设置
    
publicclassCtrlScreenShot:MonoBehaviour{//相机渲染[Header("可用渲染内容的相机")]publicCameracameraToChange;[Header("具体渲染的Layers")]publicLayerMaskCullingLayers0;publicLayerMaskCullingLayers1;publicLayerMaskCullingLayers2;// 照片存储的位置publicTransformPhotenRoot;//截图的大小模板(在场景中透明显示就行,为的就是截图时候按照这个UI的大小去截图)publicRectTransformUIRect;//LayerMaskCullingLayers;TransformphotenPos;stringphotenName;publicvoidCtrlScreenShotBtFc(intbutint){switch(butint){case0:CullingLayers =CullingLayers0;//相机渲染显示的LayersphotenPos =PhotenRoot.GetChild(0).transform;//截图显示的位置break;case1:CullingLayers =CullingLayers1;//相机渲染显示的LayersphotenPos =PhotenRoot.GetChild(1).transform;//截图显示的位置break;case2:CullingLayers =CullingLayers2;//相机渲染显示的LayersphotenPos =PhotenRoot.GetChild(2).transform;//截图显示的位置break;default:break;}StartCoroutine(StartScreenShot());}///IEnumeratorStartScreenShot(){cameraToChange.cullingMask =0;//全部剔除cameraToChange.cullingMask =CullingLayers;//显示选择的LayerscameraToChange.gameObject.SetActive(true);photenName =System.DateTime.Now.ToString("yyyyMMddHHmmss")+".png";//截图的名字stringfileName =Application.dataPath +"/StreamingAssets/"+photenName;//系统不识别标点符号,但支持中文yieldreturnStartCoroutine(CaptureByUI(UIRect,fileName));// 拼接图片路径stringimagePath =System.IO.Path.Combine(Application.streamingAssetsPath,photenName);// 开始协程加载图片yieldreturnStartCoroutine(LoadImage(imagePath,photenPos));cameraToChange.gameObject.SetActive(false);}/// <summary>/// 保存截图,并保存成png格式文件/// </summary>/// <param name="UIRect"></param>屏幕截图的大小尺寸规范 是个透明的imageUI/// <param name="mFileName"></param>将截图转换成的png文件保存的位置和命名/// <returns></returns>IEnumeratorCaptureByUI(RectTransformUIRect,stringmFileName){yieldreturnnewWaitForEndOfFrame();//等待当前帧的UI渲染完成//计算截图的宽度和高度intwidth =(int)(UIRect.rect.width);intheight =(int)(UIRect.rect.height);//创建一个新的Texture2D对象,宽度和高度与截图的宽度和高度匹配Texture2Dtex =newTexture2D(width,height,TextureFormat.RGB24,false);//计算从屏幕上读取像素的起始位置floatleftBtmX =UIRect.transform.position.x +UIRect.rect.xMin;floatleftBtmY =UIRect.transform.position.y +UIRect.rect.yMin;//使用tex.ReadPixels()函数从屏幕上读取指定区域的像素,并存储到Texture2D中。tex.ReadPixels(newRect(leftBtmX,leftBtmY,width,height),0,0);//执行读取操作,将修改应用到Texture2D中tex.Apply();//将Texture2D编码为PNG格式的字节数组byte[]bytes =tex.EncodeToPNG();//将字节数组保存为PNG图片文件System.IO.File.WriteAllBytes(mFileName,bytes);}/// <summary>/// 将保存的png,根据名字在界面上相对位置展示出来/// </summary>/// <param name="path"></param>/// <returns></returns>IEnumeratorLoadImage(stringpath,TransformphotenPos){// 发送请求获取图片UnityWebRequestwww =UnityWebRequestTexture.GetTexture(path);yieldreturnwww.SendWebRequest();// 检查请求是否成功if(www.result ==UnityWebRequest.Result.Success){// 获取加载的TextureTexture2Dtexture =DownloadHandlerTexture.GetContent(www);//创建一个RawImage并放在其位置GameObjectuiObject =newGameObject();uiObject.transform.parent =photenPos.transform;RectTransformrectTransform =uiObject.AddComponent<RectTransform>();CanvasRenderercanvasRenderer =uiObject.AddComponent<CanvasRenderer>();RawImagerawImage =uiObject.AddComponent<RawImage>();// 将加载的Texture赋值给RawImage的texture属性rawImage.texture =texture;// 调整RawImage的大小以适应图片的长宽比例rawImage.SetNativeSize();// 获取父级图像的宽度floatparentWidth =rawImage.transform.parent.GetComponent<RectTransform>().rect.width;// 计算图像的长宽比floataspectRatio =(float)rawImage.texture.height /rawImage.texture.width;// 计算应用于图像的新高度floatnewHeight =parentWidth *aspectRatio;// 设置图像的宽度和高度rawImage.rectTransform.sizeDelta =newVector2(parentWidth,newHeight);// 将图像的位置设置为零rawImage.rectTransform.localPosition =Vector3.zero;// 将图像的缩放设置为1rawImage.rectTransform.localScale =Vector3.one;}else{Debug.LogError("Failed to load image: "+www.error);}}}
用这样的方式在AR里也可以实现拍照的功能 可以切换截取的是现实的或虚拟加现实的等

http://www.ppmy.cn/news/1005976.html

相关文章

HOT74-数组中的第K个最大元素

leetcode原题链接&#xff1a;数组中的第K个最大元素 题目描述 给定整数数组 nums 和整数 k&#xff0c;请返回数组中第 k 个最大的元素。请注意&#xff0c;你需要找的是数组排序后的第 k 个最大的元素&#xff0c;而不是第 k 个不同的元素。 你必须设计并实现时间复杂度为 O…

go test

关于go test 报错 command-line-arguments go test 直接调用被测试go文件方法时候报错 command-line-arguments [command-line-arguments.test]&#xff0c;这里已经明确指出了命令参数问题 PS E:\code\mqtt> go test .\client_test.go # command-line-arguments [comma…

【数据结构与算法——TypeScript】算法的复杂度分析、 数组和链表的对比

【数据结构与算法——TypeScript】 算法的复杂度分析 什么是算法复杂度(现实案例)&#xff1f; ❤️‍&#x1f525; 前面已经解释了什么是算法&#xff1f; 其实就是解决问题的一系列步骤操作、逻辑。 ✅ 对于同一个问题&#xff0c;我们往往有很多种解决思路和方法&#x…

DoIP学习笔记系列:(四)用CAPL脚本读取DID的关键点

文章目录 1. 如何在CAPL中读取DID?1.1 避坑如何新建CAPL工程,在此不再赘述,本章主要分享一下如何在CAPL中调用DoIP接口、diag接口进行DoIP和诊断的测试。 1. 如何在CAPL中读取DID? 通常在实际项目中,会有很多DID,各种版本号、各种观测量,如果手动点,显然很麻烦,如果要…

Filebeat+ELK 部署

目录 //在 Node1 节点上操作 1&#xff0e;安装 Filebeat 2&#xff0e;设置 filebeat 的主配置文件 3&#xff0e;在 Logstash 组件所在节点上新建一个 Logstash 配置文件 4&#xff0e;浏览器访问 http://192.168.193.40:5601 登录 Kibana&#xff0c;单击“Create In…

在vue项目中封装WebSockets请求

在Vue项目中封装WebSocket请求包括以下步骤&#xff1a; 1. 安装WebSocket库&#xff1a;首先&#xff0c;导入WebSocket库&#xff0c;例如vue-native-websocket或socket.io-client。根据项目需求选择适当的库&#xff0c;并根据官方文档进行安装和配置。 2. 创建WebSocket服务…

Redis 如何解决缓存雪崩、缓存击穿、缓存穿透难题

前言 Redis 作为一门热门的缓存技术&#xff0c;引入了缓存层&#xff0c;就会有缓存异常的三个问题&#xff0c;分别是缓存击穿、缓存穿透、缓存雪崩。我们用本篇文章来讲解下如何解决&#xff01; 缓存击穿 缓存击穿: 指的是缓存中的某个热点数据过期了&#xff0c;但是此…

测试人员简单使用Jenkins

一、测试人员使用jenkins干什么&#xff1f; 部署测试环境 二、相关配置说明 一般由开发人员进行具体配置 1.Repository URL&#xff1a;填写git地址 2.填写开发分支&#xff0c;测试人员可通过相应分支进行测试环境的构建部署 当多个版本并行时&#xff0c;开发人员可以通过…