一个需求

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

如何做

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

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

  1. 首先给游戏对象分好类
  1. 简单设计一下UI,截图功能会在此操作,截图会在此展示
三个相加分别是Main 场景的主相机,DesktopUI界面UI专门展示的相机, CamTexture专门用来截图操作的相机平时不打开,只在截图时候打开截这个相机渲染的画面
  1. CamTexture想要渲染不同的画面就要对他进行不同的设置
public class CtrlScreenShot : MonoBehaviour { //相机渲染 [Header("可用渲染内容的相机")] public Camera cameraToChange; [Header("具体渲染的Layers")] public LayerMask CullingLayers0; public LayerMask CullingLayers1; public LayerMask CullingLayers2; // 照片存储的位置 public Transform PhotenRoot; //截图的大小模板(在场景中透明显示就行,为的就是截图时候按照这个UI的大小去截图) public RectTransform UIRect; // LayerMask CullingLayers; Transform photenPos; string photenName; public void CtrlScreenShotBtFc(int butint) { switch (butint) { case 0: CullingLayers = CullingLayers0; //相机渲染显示的Layers photenPos = PhotenRoot.GetChild(0).transform;//截图显示的位置 break; case 1: CullingLayers = CullingLayers1; //相机渲染显示的Layers photenPos = PhotenRoot.GetChild(1).transform;//截图显示的位置 break; case 2: CullingLayers = CullingLayers2; //相机渲染显示的Layers photenPos = PhotenRoot.GetChild(2).transform;//截图显示的位置 break; default: break; } StartCoroutine(StartScreenShot()); } /// IEnumerator StartScreenShot() { cameraToChange.cullingMask = 0; //全部剔除 cameraToChange.cullingMask = CullingLayers; //显示选择的Layers cameraToChange.gameObject.SetActive(true); photenName = System.DateTime.Now.ToString("yyyyMMddHHmmss") + ".png";//截图的名字 string fileName = Application.dataPath + "/StreamingAssets/" + photenName;//系统不识别标点符号,但支持中文 yield return StartCoroutine(CaptureByUI(UIRect, fileName)); // 拼接图片路径 string imagePath = System.IO.Path.Combine(Application.streamingAssetsPath, photenName); // 开始协程加载图片 yield return StartCoroutine(LoadImage(imagePath, photenPos)); cameraToChange.gameObject.SetActive(false); } /// <summary> /// 保存截图,并保存成png格式文件 /// </summary> /// <param name="UIRect"></param>屏幕截图的大小尺寸规范 是个透明的imageUI /// <param name="mFileName"></param>将截图转换成的png文件保存的位置和命名 /// <returns></returns> IEnumerator CaptureByUI(RectTransform UIRect, string mFileName) { yield return new WaitForEndOfFrame(); //等待当前帧的UI渲染完成 //计算截图的宽度和高度 int width = (int)(UIRect.rect.width); int height = (int)(UIRect.rect.height); //创建一个新的Texture2D对象,宽度和高度与截图的宽度和高度匹配 Texture2D tex = new Texture2D(width, height, TextureFormat.RGB24, false); //计算从屏幕上读取像素的起始位置 float leftBtmX = UIRect.transform.position.x + UIRect.rect.xMin; float leftBtmY = UIRect.transform.position.y + UIRect.rect.yMin; //使用tex.ReadPixels()函数从屏幕上读取指定区域的像素,并存储到Texture2D中。 tex.ReadPixels(new Rect(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> IEnumerator LoadImage(string path, Transform photenPos) { // 发送请求获取图片 UnityWebRequest www = UnityWebRequestTexture.GetTexture(path); yield return www.SendWebRequest(); // 检查请求是否成功 if (www.result == UnityWebRequest.Result.Success) { // 获取加载的Texture Texture2D texture = DownloadHandlerTexture.GetContent(www); //创建一个RawImage并放在其位置 GameObject uiObject = new GameObject(); uiObject.transform.parent = photenPos.transform; RectTransform rectTransform = uiObject.AddComponent<RectTransform>(); CanvasRenderer canvasRenderer = uiObject.AddComponent<CanvasRenderer>(); RawImage rawImage = uiObject.AddComponent<RawImage>(); // 将加载的Texture赋值给RawImage的texture属性 rawImage.texture = texture; // 调整RawImage的大小以适应图片的长宽比例 rawImage.SetNativeSize(); // 获取父级图像的宽度 float parentWidth = rawImage.transform.parent.GetComponent<RectTransform>().rect.width; // 计算图像的长宽比 float aspectRatio = (float)rawImage.texture.height / rawImage.texture.width; // 计算应用于图像的新高度 float newHeight = parentWidth * aspectRatio; // 设置图像的宽度和高度 rawImage.rectTransform.sizeDelta = new Vector2(parentWidth, newHeight); // 将图像的位置设置为零 rawImage.rectTransform.localPosition = Vector3.zero; // 将图像的缩放设置为1 rawImage.rectTransform.localScale = Vector3.one; } else { Debug.LogError("Failed to load image: " + www.error); } } }
用这样的方式在AR里也可以实现拍照的功能 可以切换截取的是现实的或虚拟加现实的等
Logo

分享前沿Unity技术干货和开发经验,精彩的Unity活动和社区相关信息

更多推荐