Unity Image/GL实现一个框选功能吧

news2024/11/19 18:33:56
  1. 场景准备
    在这里插入图片描述

  2. 准备一张框选背景图
    导入到unity之后,修改 Texture Type 为 Sprite,(根据图片需要)在 Sprite Editor 中 编辑 九宫格格式。图片样式的不一致,设置的九宫格格式也不一致。本例中虚线部分需要等距离平铺,所以如下设置即可满足要求。
    在这里插入图片描述

  3. Image组件设置
    pivot的正确设置很重要,否则当我们更新Image尺寸的时候,尺寸更新了,不跟随鼠标
    由于我选择的框选图片背景是虚线格式的,虚线部分想等距平铺,所以这里Image Type选择Tiled即可。
    然后添加boxSelection脚本。实现框选功能。
    在这里插入图片描述
    这里是在Update里面通过获取鼠标当前操作,更新image尺寸实现的框选,在鼠标松开时,检测3d区域内物体是否在框选范围内即可。实现方式非常简单易懂,且性能损耗比较小。

	public class BoxSelection : MonoBehaviour
    {
        public Material normalMat;
        public Material highlightMat;
        public Transform root;
        
        private RectTransform selectionBoxRectTrans;
        private Canvas canvas;
        private bool onDrawingRect;
        private Vector2  startPoint;
        private Vector2  endPoint;
        private Selector selector;
        
        private void Start()
        {
            canvas = GetComponentInParent<Canvas>();
            selectionBoxRectTrans = GetComponent<RectTransform>();
        }

        void Update()
        {
            if (Input.GetMouseButtonDown(0))
            {
                onDrawingRect = true;
                startPoint = Input.mousePosition;
            }

            if (onDrawingRect)
            {
                UpdateSelection();
            }

            if (onDrawingRect && Input.GetMouseButtonUp(0))
            {
                endPoint = Input.mousePosition;
                onDrawingRect = false;
                ClearSelection();
                selector = new Selector(startPoint, endPoint);
                Selection(selector);
            }
        }
        
        void UpdateSelection()
        {
            Vector2 currentPoint = Input.mousePosition;
            float minX = Mathf.Min(currentPoint.x, startPoint.x);
            float minY = Mathf.Min(currentPoint.y, startPoint.y);
            float maxX = Mathf.Max(currentPoint.x, startPoint.x);
            float maxY = Mathf.Max(currentPoint.y, startPoint.y);
            selectionBoxRectTrans.position = new Vector3(minX, minY, 0);
            selectionBoxRectTrans.sizeDelta = new Vector2(Mathf.Abs(maxX - minX) / canvas.scaleFactor, Mathf.Abs(maxY - minY) / canvas.scaleFactor);
        }

        void ClearSelection()
        {
            selectionBoxRectTrans.sizeDelta = Vector2.zero;
        }
     
        void Selection(Selector selector)
        {
            foreach(Transform child in root)
            {
                Vector3 screenPos = Camera.main.WorldToScreenPoint(child.position);
                if (screenPos.x > selector.Xmin && screenPos.x < selector.Xmax && screenPos.y > selector.Ymin && screenPos.y < selector.Ymax)
                {
                    child.GetComponent<MeshRenderer>().material = highlightMat;
                }
                else
                {
                    child.GetComponent<MeshRenderer>().material = normalMat;
                }
            }
        }
        
        private class Selector
        {
            public float Xmin;
            public float Xmax;
            public float Ymin;
            public float Ymax;
     
            //构造函数,在创建选定框时自动计算Xmin/Xmax/Ymin/Ymax
            public Selector(Vector3 start, Vector3 end)
            {
                Xmin = Mathf.Min(start.x, end.x);
                Xmax = Mathf.Max(start.x, end.x);
                Ymin = Mathf.Min(start.y, end.y);
                Ymax = Mathf.Max(start.y, end.y);
            }
        }
    }

当然,也可以不使用Image组件,我们可以通过GL绘制的方式,通过OnGUI或者OnPostRender的方法绘制【框】。不需要九宫格图片,将脚本挂载在Camera上即可。
// 画框代码

        public Color GLRectColor;
        public Color GLRectEdgeColor;

        private bool onDrawingRect;
        private Vector3 startPoint;
        private Vector3 currentPoint;
        private Vector3 endPoint;
      
        private void Start()
        {
            InitMaterial();
        }
        
        protected Material lineMaterial;

        protected void InitMaterial()
        {
            if (!lineMaterial)
            {
                // Unity3d使用该默认的Shader作为线条材质    
                Shader shader = Shader.Find("Hidden/Internal-Colored");
                lineMaterial = new Material(shader);
                lineMaterial.hideFlags = HideFlags.HideAndDontSave;
                // 开启 alpha blending    
                lineMaterial.SetInt("_SrcBlend", (int)BlendMode.SrcAlpha);
                lineMaterial.SetInt("_DstBlend", (int)BlendMode.OneMinusSrcAlpha);
                // 开启背面遮挡    
                lineMaterial.SetInt("_Cull", (int)CullMode.Off);
                // Turn off depth writes    
                lineMaterial.SetInt("_ZWrite", 0);
                lineMaterial.SetInt("_ZTest", (int)CompareFunction.Always);
            }
        }

		void Update()
        {
            if (Input.GetMouseButtonDown(0))
            {
                onDrawingRect = true;
                startPoint = Input.mousePosition;
            }

            if (Input.GetMouseButtonUp( 0 ) )
            {
                onDrawingRect = false;
            }
        }
        
		void OnGUI()
        {
            if (onDrawingRect)
            {
            	// GL线条材质
                if (!lineMaterial)
                    return;

                currentPoint = Input.mousePosition;
        
        		// 根据起始点和现在鼠标位置,便可以获取框的四个点的坐标!
                Vector3 p0 = new Vector3(startPoint.x, Screen.height - startPoint.y, 0);
                Vector3 p1 = new Vector3(currentPoint.x, Screen.height - startPoint.y, 0);
                Vector3 p2 = new Vector3(currentPoint.x, Screen.height - currentPoint.y, 0);
                Vector3 p3 = new Vector3(startPoint.x, Screen.height - currentPoint.y, 0);
        
                lineMaterial.SetPass(0);
        
                GL.PushMatrix();
                // GL.LoadPixelMatrix();
                
                /*------第一步,绘制矩形------*/
                GL.Begin(GL.QUADS);
                GL.Color(GLRectColor); // 自己设置颜色
                GL.Vertex(p0);
                GL.Vertex(p1);
                GL.Vertex(p2);
                GL.Vertex(p3);
                GL.End();
        
                /*------第二步,绘制矩形的边框------*/
                GL.Begin(GL.LINES); 
                GL.Color(GLRectEdgeColor); // 自己设置颜色
                
                GL.Vertex(p0);
                GL.Vertex(p1);
        
                GL.Vertex(p1);
                GL.Vertex(p2);
        
                GL.Vertex(p2);
                GL.Vertex(p3);
        
                GL.Vertex(p3);
                GL.Vertex(p0);
                GL.End();
        
                GL.PopMatrix();
            }
        }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/691605.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Visual C++类的继承及类中成员的访问特性——搞懂public、protected、private

我是荔园微风&#xff0c;作为一名在IT界整整25年的老兵&#xff0c;今天来说说Visual C中类的继承及类中成员的访问特性&#xff0c;也就是来搞懂public、protected、private这三个东西。 很多人搞不清楚这三个东西&#xff0c;并且很容易弄错&#xff0c;其实不是学习的人的…

vr全景在线虚拟展馆节约企业成本费用

博物馆作为人们了解历史、文化和艺术的重要场所&#xff0c;现在可以通过VR全景技术来进行展览&#xff0c;让参观者身临其境地感受历史文化的魅力。本文将介绍博物馆VR全景的特点、优势&#xff0c;以及如何使用VR全景技术来使得博物馆的展览和教育活动更丰富。 参观者可以对内…

【Linux】权限理解

Linux权限理解 shell外壳运行原理为什么我们不是直接访问操作系统&#xff1f;外壳程序的意义 权限的概念与操作用户的权限如何进行Linux下用户身份的切换? 角色和文件的权限权限是什么&#xff1f;Linux中文件的类型是如何被确定的&#xff1f;权限与角色的关系权限与文件属性…

玩机搞机---修改系统固件不开机 安卓13去除系统app签名验证的几种方法

谷歌在安卓13中对系统应用添加了一层校验验证&#xff0c;你如果修改了系统app.那么原有的签名加载后过不去验证&#xff0c;会导致进不去系统卡第一屏或者进入系统后修改的app错误等等故障。 Android 13增加了新的apk签名校验机制&#xff0c;现在开机中它会对所有系统分区&a…

Hive中怎样创建和查询视图信息?

视图是从数据库的数据表中选取出来的数据组成的逻辑窗口&#xff0c;它是一个虚拟机表。引入视图后&#xff0c;用户可以将注意力集中在关心的数据上&#xff0c;如果数据来源于多个基本表结构&#xff0c;并且搜索条件比较复杂时&#xff0c;需要编写的查询语句就会比较烦琐&a…

hivesql 将数据处理成复杂json

类型一 原数据&#xff1a;bankid是array类型 目标数据&#xff1a; {"bankname": ["SPDB", "WS_HBBANK", "mytest"],"grid": [{"name": "阶段1","values": ["38.0,1.0,1.0"]}…

安全生产月评选活动-优秀的“安全之星”,塑造榜样力量

安全生产月评选活动-优秀的“安全之星”&#xff0c;塑造榜样力量。 推荐功能&#xff1a;投票 企业可以举办安全生产月评选活动&#xff0c;选出优秀的“安全之星”&#xff0c;进行内部评选&#xff0c;塑造榜样力量。 首先&#xff0c;让我们先来了解一下“安全生产月评选活…

MYSQL各种log

本章纲要 1、mysql主从复制是怎么实现的&#xff08;binlog,relaylog&#xff09; 2、事物执行原理是怎么保证ACID的&#xff08;redolog,undolog&#xff09; 一、Mysql是怎么实现主从复制的 数据库主从设计的好处&#xff1a; 1、实现读写分离&#xff0c;方便扩展&#…

MySQL 磁盘爆了,是 optimize table 的锅

2023-06-26 22:17左右&#xff0c;收到某系统的主库磁盘使用率告警。2023-06-26 23:02左右收到该系统的从库磁盘使用率告警。 收到告警后&#xff0c;登录数据库查看各表的磁盘使用。 经分析发现DB存在一个当日的备份表t_eap_sys_navigation_log_bak_20230626 &#xff0c;且在…

4077:出栈序列统计

codeup【递归入门】出栈序列统计_codeup编程_战斗的咸鱼的博客-CSDN博客 #include<iostream> using namespace std; int n,sum,ans; void dfs(int out,int in,int not_in){if(outn){ans;return;}if(in>0) dfs(out1,in-1,not_in);if(not_in>0&&in<n) dfs…

Vue模板编译

文章目录 导文Vue模板编译是什么&#xff1f;模拟编译模板总结 导文 Vue框架使用了模板编译的方式来将Vue模板转换为可执行的JavaScript代码。这个编译过程在运行时由Vue的编译器完成。 在Vue中&#xff0c;模板是以HTML标记的形式编写的&#xff0c;其中可以包含Vue的特殊语法…

【探索 Kubernetes|作业管理篇 系列 14】StatefulSet 存储状态

前言 大家好&#xff0c;我是秋意零。 在上一篇中&#xff0c;我们讲解了 StatefulSet 的拓扑状态&#xff1b;我们发现&#xff0c;它的拓扑状态&#xff0c;就是顺序启动/删除、Pod 名称编号命名、将 Pod 名称设为 Hostname 名称、通过 Service 无头服务的 DNS 记录访问。 …

基于Python的海量豆瓣电影、数据获取、数据预处理、数据分析、可视化、大屏设计项目(含数据库)

目录 项目介绍研究背景国内外研究现状分析研究目的研究意义研究总体设计网络爬虫介绍豆瓣电影数据的采集数据预处理大数据分析及可视化豆瓣影评结构化分析 大屏可视化文本可视化总结每文一语 项目介绍 有需要本项目的代码或文档以及全部资源&#xff0c;或者部署调试可以私信博…

虹科DataHub:连接工业自动化的桥梁,引领企业数字化转型

一、前言 随着智能制造、工业互联网等新一代信息技术的不断发展&#xff0c;IT和OT融合已成为未来制造业数字化转型的重要趋势。得益于开放的系统架构和创新的软件应用&#xff0c;OT&#xff08;工业自动化技术&#xff09;和信息技术&#xff08;IT&#xff09;系统之间的数…

在windows系统中映射网络驱动器时,如何通过非455端口远程访问Linux服务器的Samba服务

声明 通常情况下&#xff0c;在windows中通过Linux服务器的Samba服务去映射网络驱动器时候&#xff0c;一般默认就是直接填入内网Linux服务器ip即可&#xff0c;它会默认445端口。若是我的windows并不和Linux服务器在一个网段时&#xff0c;该如何操作呢&#xff1f; 1 用管理…

一键转发微信好友朋友圈,自动跟圈

今天咱来讲一下如何实现一键转发朋友圈&#xff1f; 如何一键跟圈&#xff0c;多个微信快速同步发圈&#xff1f; 01 一键转发 浏览朋友圈&#xff0c;在此页面可以浏览所登录的微信号的好友朋友圈&#xff0c;可以实现快速点赞、评论、一键转发。 单击“转发”即可跳转到发…

D. Optical Experiment

题意&#xff1a; D. 光学实验 时间限制&#xff1a;5秒 内存限制&#xff1a;256兆字节 输入&#xff1a;标准输入 输出&#xff1a;标准输出 Phunsuk Wangdu教授进行了一些关于光线的实验。n条光线的实验装置如下&#xff1a; 有一个长方形盒子&#xff0c;在相对的两面…

windows的环回网卡(loopback adapter) 安装方法

0.说明&#xff1a;windows的环回网卡(loopback adapter)的作用&#xff1a; microsoft loopback adapter就是安装在本机上的一块虚拟网卡&#xff0c;它跟本机上的其它物理网卡、和物理网卡连接的网络是没有关系的&#xff0c;你可以理解成这块网卡上的网线接到了另外一个空白…

葡萄风味有奥秘,农科院用机器学习揭示基因渐渗过程

内容一览&#xff1a;基因渐渗与葡萄的驯化、遗传改良密切相关。先前研究揭示了欧洲栽培葡萄中&#xff0c;野生葡萄基因渐渗的基因组信号&#xff0c;但尚未深入研究这些渐渗事件发生的时间、方式、基因组模式和生物学效应。本文中&#xff0c;中国农业科学院深圳农业基因组研…

【杂谈理解】电源芯片设计选型

前言 看B站UP主达尔闻关于电源视频&#xff0c;做的笔记。下述内容中&#xff0c;如有芯片比较皆是性能层面的比较&#xff0c;暂未考虑成本。且老师在视频中&#xff0c;也多次建议说&#xff0c;可以多关注比较新兴的芯片&#xff0c;一般会是有更好的性能。讲的真的很好&…