unity 自由框选截图(两种方法,亲测有效)

2023-12-08 15:52

本文主要是介绍unity 自由框选截图(两种方法,亲测有效),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

提示:文章有错误的地方,还望诸位大神不吝指教!

文章目录

  • 前言
  • 一、第一种方法
    • (1)简介GL
    • (2) GL 用法:
    • (3)具体代码
  • 二、第二种方法
    • 第一步:
    • 第二步
    • 第三步 代码
  • 总结


前言

unity版本2019.3.7f1

本文提供两种截图方式,都是亲测可用。
第一种使用GL画线来实现
第二种使用Image来实现
总的逻辑都是一样的。
下面是两种方式的效果图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

提示:以下是本篇文章正文内容,下面案例可供参考

一、第一种方法

使用GL来画一个框,作为截图区域。

(1)简介GL

Graphics Library(简称 GL),包含一系列类似 OpenGL 的 Immediate 模式的渲染指令,比 Graphic.DrawMesh() 更高效。GL 是立即执行的,如果在Update() 方法里调用,它们将在相机渲染前执行,相机渲染前会清空屏幕,GL 渲染效果将无法看到。

(2) GL 用法:

在相机上挂脚本,并在 OnPostRender() 方法里执行(MonoBehaviour的生命周期)。GL 渲染的图像不需要 GameObject 承载,在 Hierarchy 窗口不会生成 GameObject 对象。
另外需要给一个Material 作为材质

(3)具体代码

记得挂载在相机上,并且给一个Material 。

/**********************************************************************文件信息文件名(File Name):                SelectScreenshot.cs作者(Author):                      野区捕龙为宠创建时间(CreateTime):             #CREATETIME#**********************************************************************/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System;
using System.IO;namespace Twq
{public class SelectScreenshot : MonoBehaviour{private Color rColor = Color.green;private Vector3 start = Vector3.zero;private Vector3 end = Vector3.zero;public Material rMat;private bool drawFlag = false;private Rect rect;private Texture2D cutImage;// Use this for initialization  void Start(){}// Update is called once per frame  void Update(){if (Input.GetMouseButtonDown(0)){drawFlag = true;//如果鼠标左键按下 设置开始画线标志  start = Input.mousePosition;//记录按下位置  end = Input.mousePosition;//鼠标当前位置  }else if (Input.GetMouseButtonUp(0)){drawFlag = false;//如果鼠标左键放开 结束画线  }if (Input.GetKeyDown(KeyCode.M)){StartCoroutine(CutImage());}}//绘制框选  void OnPostRender(){//画线这种操作推荐在OnPostRender()里进行 而不是直接放在Update,所以需要标志来开启  if (drawFlag){end = Input.mousePosition;//鼠标当前位置  }GL.PushMatrix();//保存摄像机变换矩阵  if (!rMat)return;rMat.SetPass(0);GL.LoadPixelMatrix();//设置用屏幕坐标绘图  GL.Begin(GL.LINES);GL.Color(rColor);//设置方框的边框颜色 边框不透明  GL.Vertex3(start.x, start.y, 0);GL.Vertex3(end.x, start.y, 0);GL.Vertex3(end.x, start.y, 0);GL.Vertex3(end.x, end.y, 0);GL.Vertex3(end.x, end.y, 0);GL.Vertex3(start.x, end.y, 0);GL.Vertex3(start.x, end.y, 0);GL.Vertex3(start.x, start.y, 0);GL.End();GL.PopMatrix();//恢复摄像机投影矩阵  }IEnumerator CutImage(){string date = System.DateTime.Now.ToString("yyyyMMddHHmmss");//图片大小    cutImage = new Texture2D((int)(end.x - start.x), (int)(start.y - end.y), TextureFormat.RGB24, true);//坐标左下角为0    rect = new Rect((int)start.x, Screen.height - (int)(Screen.height - end.y), (int)(end.x - start.x), (int)(start.y - end.y));yield return new WaitForEndOfFrame();cutImage.ReadPixels(rect, 0, 0, true);cutImage.Apply();yield return cutImage;byte[] byt = cutImage.EncodeToPNG();//保存截图    File.WriteAllBytes(Application.streamingAssetsPath + "/ImageName" + date + ".png", byt);}}
}

二、第二种方法

原理都差不多,第二种扩展性更好一些。
需要创建4个UI,来充当线框。并设置好Anchors。

第一步:

创建一个父节点,以及子节点。如下图:
在这里插入图片描述
在这里插入图片描述

第二步

分别创建4个UI,充当4边线框,并设置每个边其Anchors。如下图:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

第三步 代码

using System.Collections;
using System.Collections.Generic;
//using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;public class MarkerPointSet : MonoBehaviour
{private Vector3 m_Point;// private PointBase m_PointBase;private List<GameObject> m_Images = new List<GameObject>();List<Texture2D> m_AddListTexture = new List<Texture2D>();//private BaoGaoPoint m_BaoGaoPoint;private Texture2D m_screenShot;//画框截图public GameObject m_LineNode;public GameObject m_LeftLine;public GameObject m_RightLine;public GameObject m_DownLine;public GameObject m_UpLine;private Vector3 m_StartLine = Vector3.zero;private Vector3 m_EndLien = Vector3.zero;private bool m_IsScreens = false;private bool m_IsMouseEnd = false;void Start(){m_IsScreens = true;}private void Update(){if (m_IsScreens == true){m_EndLien = Input.mousePosition;if (Input.GetMouseButtonDown(0)){m_StartLine = Input.mousePosition;m_LineNode.gameObject.SetActive(true);m_IsMouseEnd = true;}else if(Input.GetMouseButtonUp(0)){if (m_IsMouseEnd == true){m_EndLien = Input.mousePosition;m_IsScreens = false;m_IsMouseEnd = false;//m_Buttons.SetActive(true);//m_Buttons.transform.position = Input.mousePosition;int _x = (int)m_StartLine.x;int _y = (int)m_StartLine.y;int _w = (int) (m_StartLine.x - m_EndLien.x);int _h = (int)(m_StartLine.y - m_EndLien.y);if (_w < 0){_w = Mathf.Abs(_w);}else{_x -= _w;}if (_h < 0){_h = Mathf.Abs(_h);}else{_y -= _h;}StartCoroutine(CaptureScreen(new Rect(_x,_y,_w,_h)));}}if (m_IsMouseEnd == true){UpdateLine();}}}private void UpdateLine(){m_LeftLine.transform.position = m_StartLine;m_DownLine.transform.position = m_StartLine;m_RightLine.transform.position = m_EndLien;m_UpLine.transform.position = m_EndLien;float _x = m_StartLine.x - m_EndLien.x;float _y = m_StartLine.y - m_EndLien.y;if (_x >=0){RectTransform _dtrans = m_DownLine.GetComponent<RectTransform>();_dtrans.sizeDelta = new Vector2(_x,2f);RectTransform _utrans = m_UpLine.GetComponent<RectTransform>();_utrans.sizeDelta = new Vector2(_x, 2f);_dtrans.localScale = new Vector3(-1f,1f,1f);_utrans.localScale = new Vector3(-1f, 1f, 1f);} else{_x = Mathf.Abs(_x);RectTransform _dtrans = m_DownLine.GetComponent<RectTransform>();_dtrans.sizeDelta = new Vector2(_x, 2f);RectTransform _utrans = m_UpLine.GetComponent<RectTransform>();_utrans.sizeDelta = new Vector2(_x, 2f);_dtrans.localScale = new Vector3(1f, 1f, 1f);_utrans.localScale = new Vector3(1f, 1f, 1f);}if (_y >= 0){RectTransform _dtrans = m_LeftLine.GetComponent<RectTransform>();_dtrans.sizeDelta = new Vector2(2f, _y);RectTransform _utrans = m_RightLine.GetComponent<RectTransform>();_utrans.sizeDelta = new Vector2(2f, _y);_dtrans.localScale = new Vector3(1f, -1f, 1f);_utrans.localScale = new Vector3(1f, -1f, 1f);}else{_y = Mathf.Abs(_y);RectTransform _dtrans = m_LeftLine.GetComponent<RectTransform>();_dtrans.sizeDelta = new Vector2(2f, _y);RectTransform _utrans = m_RightLine.GetComponent<RectTransform>();_utrans.sizeDelta = new Vector2(2f, _y);_dtrans.localScale = new Vector3(1f, 1f, 1f);_utrans.localScale = new Vector3(1f, 1f, 1f);}}private IEnumerator CaptureScreen(Rect rect){yield return new WaitForEndOfFrame();//不显示UI截图RenderTexture _rt = new RenderTexture(1920,1080,0);Camera.main.targetTexture = _rt;//传到主摄像机上Camera.main.Render();//渲染RenderTexture.active = _rt;m_screenShot = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.RGB24, false);m_screenShot.ReadPixels(rect, 0, 0);m_screenShot.Apply();Camera.main.targetTexture = null;RenderTexture.active = null;Destroy(_rt);//m_Image.gameObject.SetActive(true);//m_Image.rectTransform.sizeDelta = new Vector2(m_screenShot.width, m_screenShot.height);//图片设置//m_Image.sprite = Sprite.Create(m_screenShot, new Rect(0, 0, m_screenShot.width, m_screenShot.height), Vector2.zero);yield break;}}

项目链接: link:

总结

好记性不如烂笔头

这篇关于unity 自由框选截图(两种方法,亲测有效)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/470442

相关文章

解读为什么@Autowired在属性上被警告,在setter方法上不被警告问题

《解读为什么@Autowired在属性上被警告,在setter方法上不被警告问题》在Spring开发中,@Autowired注解常用于实现依赖注入,它可以应用于类的属性、构造器或setter方法上,然... 目录1. 为什么 @Autowired 在属性上被警告?1.1 隐式依赖注入1.2 IDE 的警告:

SpringBoot快速接入OpenAI大模型的方法(JDK8)

《SpringBoot快速接入OpenAI大模型的方法(JDK8)》本文介绍了如何使用AI4J快速接入OpenAI大模型,并展示了如何实现流式与非流式的输出,以及对函数调用的使用,AI4J支持JDK8... 目录使用AI4J快速接入OpenAI大模型介绍AI4J-github快速使用创建SpringBoot

Android开发中gradle下载缓慢的问题级解决方法

《Android开发中gradle下载缓慢的问题级解决方法》本文介绍了解决Android开发中Gradle下载缓慢问题的几种方法,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、网络环境优化二、Gradle版本与配置优化三、其他优化措施针对android开发中Gradle下载缓慢的问

python 3.8 的anaconda下载方法

《python3.8的anaconda下载方法》本文详细介绍了如何下载和安装带有Python3.8的Anaconda发行版,包括Anaconda简介、下载步骤、安装指南以及验证安装结果,此外,还介... 目录python3.8 版本的 Anaconda 下载与安装指南一、Anaconda 简介二、下载 An

Java中将异步调用转为同步的五种实现方法

《Java中将异步调用转为同步的五种实现方法》本文介绍了将异步调用转为同步阻塞模式的五种方法:wait/notify、ReentrantLock+Condition、Future、CountDownL... 目录异步与同步的核心区别方法一:使用wait/notify + synchronized代码示例关键

Python使用Pandas对比两列数据取最大值的五种方法

《Python使用Pandas对比两列数据取最大值的五种方法》本文主要介绍使用Pandas对比两列数据取最大值的五种方法,包括使用max方法、apply方法结合lambda函数、函数、clip方法、w... 目录引言一、使用max方法二、使用apply方法结合lambda函数三、使用np.maximum函数

Qt 中集成mqtt协议的使用方法

《Qt中集成mqtt协议的使用方法》文章介绍了如何在工程中引入qmqtt库,并通过声明一个单例类来暴露订阅到的主题数据,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录一,引入qmqtt 库二,使用一,引入qmqtt 库我是将整个头文件/源文件都添加到了工程中进行编译,这样 跨平台

Nginx设置连接超时并进行测试的方法步骤

《Nginx设置连接超时并进行测试的方法步骤》在高并发场景下,如果客户端与服务器的连接长时间未响应,会占用大量的系统资源,影响其他正常请求的处理效率,为了解决这个问题,可以通过设置Nginx的连接... 目录设置连接超时目的操作步骤测试连接超时测试方法:总结:设置连接超时目的设置客户端与服务器之间的连接

Java判断多个时间段是否重合的方法小结

《Java判断多个时间段是否重合的方法小结》这篇文章主要为大家详细介绍了Java中判断多个时间段是否重合的方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录判断多个时间段是否有间隔判断时间段集合是否与某时间段重合判断多个时间段是否有间隔实体类内容public class D

Python使用国内镜像加速pip安装的方法讲解

《Python使用国内镜像加速pip安装的方法讲解》在Python开发中,pip是一个非常重要的工具,用于安装和管理Python的第三方库,然而,在国内使用pip安装依赖时,往往会因为网络问题而导致速... 目录一、pip 工具简介1. 什么是 pip?2. 什么是 -i 参数?二、国内镜像源的选择三、如何