思路:

  在uinity中既可以将屏幕坐标转换为世界坐标,也可以将世界坐标转换为屏幕坐标。这样的话我们就可以通过判断物体在世界坐标转换为平幕坐标是否在鼠标框选的矩形区域坐标内,来判断物体是否在框选范围。

使用到的API:

  GL:http://wiki.ceeger.com/script/unityengine/classes/gl/gl,用来实现在鼠标拖动时在屏幕中绘制出矩形区域。

    Camera:http://wiki.ceeger.com/script/unityengine/classes/camera/camera.worldtoscreenpoint,将世界坐标转换为屏幕坐标

实现:(转载踏浪星空

将可选取的对象放置在 characters集合中,rectMat的材质为使用sprite下的default类型的shader的材质即可。

  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4.  
  5. public class SelectObjects : MonoBehaviour
  6. {
  7.  
  8. public List<GameObject> characters;
  9. public Color rectColor = Color.green;
  10.  
  11. private Vector3 start = Vector3.zero;//记下鼠标按下位置
  12.  
  13. // private Material rectMat = null;//画线的材质 不设定系统会用当前材质画线 结果不可控
  14. public Material rectMat = null;//这里使用Sprite下的defaultshader的材质即可
  15.  
  16. private bool drawRectangle = false;//是否开始画线标志
  17.  
  18. // Use this for initialization
  19.  
  20. void Start()
  21. {
  22.  
  23. // rectMat = new Material("Shader \"Lines/Colored Blended\" {" +
  24. //
  25. // "SubShader { Pass { " +
  26. //
  27. // " Blend SrcAlpha OneMinusSrcAlpha " +
  28. //
  29. // " ZWrite Off Cull Off Fog { Mode Off } " +
  30. //
  31. // " BindChannels {" +
  32. //
  33. // " Bind \"vertex\", vertex Bind \"color\", color }" +
  34. //
  35. // "} } }");//生成画线的材质
  36.  
  37. rectMat.hideFlags = HideFlags.HideAndDontSave;
  38.  
  39. rectMat.shader.hideFlags = HideFlags.HideAndDontSave;//不显示在hierarchy面板中的组合,不保存到场景并且卸载Resources.UnloadUnusedAssets不卸载的对象。
  40.  
  41. }
  42.  
  43. void Update()
  44. {
  45.  
  46. if (Input.GetMouseButtonDown())
  47. {
  48.  
  49. drawRectangle = true;//如果鼠标左键按下 设置开始画线标志
  50.  
  51. start = Input.mousePosition;//记录按下位置
  52.  
  53. }
  54. else if (Input.GetMouseButtonUp())
  55. {
  56.  
  57. drawRectangle = false;//如果鼠标左键放开 结束画线
  58. checkSelection(start,Input.mousePosition);
  59. }
  60. }
  61.  
  62. void OnPostRender()
  63. {//画线这种操作推荐在OnPostRender()里进行 而不是直接放在Update,所以需要标志来开启
  64.  
  65. if (drawRectangle)
  66. {
  67.  
  68. Vector3 end = Input.mousePosition;//鼠标当前位置
  69.  
  70. GL.PushMatrix();//保存摄像机变换矩阵,把投影视图矩阵和模型视图矩阵压入堆栈保存
  71.  
  72. if (!rectMat)
  73.  
  74. return;
  75.  
  76. rectMat.SetPass();//为渲染激活给定的pass。
  77.  
  78. GL.LoadPixelMatrix();//设置用屏幕坐标绘图
  79.  
  80. GL.Begin(GL.QUADS);//开始绘制矩形
  81.  
  82. GL.Color(new Color(rectColor.r, rectColor.g, rectColor.b, 0.1f));//设置颜色和透明度,方框内部透明
  83.  
  84. //绘制顶点
  85. GL.Vertex3(start.x, start.y, );
  86.  
  87. GL.Vertex3(end.x, start.y, );
  88.  
  89. GL.Vertex3(end.x, end.y, );
  90.  
  91. GL.Vertex3(start.x, end.y, );
  92.  
  93. GL.End();
  94.  
  95. GL.Begin(GL.LINES);//开始绘制线
  96.  
  97. GL.Color(rectColor);//设置方框的边框颜色 边框不透明
  98.  
  99. GL.Vertex3(start.x, start.y, );
  100.  
  101. GL.Vertex3(end.x, start.y, );
  102.  
  103. GL.Vertex3(end.x, start.y, );
  104.  
  105. GL.Vertex3(end.x, end.y, );
  106.  
  107. GL.Vertex3(end.x, end.y, );
  108.  
  109. GL.Vertex3(start.x, end.y, );
  110.  
  111. GL.Vertex3(start.x, end.y, );
  112.  
  113. GL.Vertex3(start.x, start.y, );
  114.  
  115. GL.End();
  116.  
  117. GL.PopMatrix();//恢复摄像机投影矩阵
  118.  
  119. }
  120.  
  121. }
  122.  
  123. //检测被选择的物体
  124. void checkSelection(Vector3 start, Vector3 end)
  125. {
  126.  
  127. Vector3 p1 = Vector3.zero;
  128.  
  129. Vector3 p2 = Vector3.zero;
  130.  
  131. if (start.x > end.x)
  132. {//这些判断是用来确保p1的xy坐标小于p2的xy坐标,因为画的框不见得就是左下到右上这个方向的
  133.  
  134. p1.x = end.x;
  135.  
  136. p2.x = start.x;
  137.  
  138. }
  139.  
  140. else {
  141.  
  142. p1.x = start.x;
  143.  
  144. p2.x = end.x;
  145.  
  146. }
  147.  
  148. if (start.y > end.y)
  149. {
  150.  
  151. p1.y = end.y;
  152.  
  153. p2.y = start.y;
  154.  
  155. }
  156.  
  157. else {
  158.  
  159. p1.y = start.y;
  160.  
  161. p2.y = end.y;
  162.  
  163. }
  164.  
  165. foreach (GameObject obj in characters)
  166. {//把可选择的对象保存在characters数组里
  167.  
  168. Vector3 location = Camera.main.WorldToScreenPoint(obj.transform.position);//把对象的position转换成屏幕坐标
  169.  
  170. if (location.x < p1.x || location.x > p2.x || location.y < p1.y || location.y > p2.y
  171.  
  172. || location.z < Camera.main.nearClipPlane || location.z > Camera.main.farClipPlane)//z方向就用摄像机的设定值,看不见的也不需要选择了
  173.  
  174. {
  175. //disselecting(obj);//上面的条件是筛选 不在选择范围内的对象,然后进行取消选择操作,比如把物体放到default层,就不显示轮廓线了
  176. print("---"+obj.name);
  177. }
  178.  
  179. else
  180.  
  181. {
  182. //selecting(obj);//否则就进行选中操作,比如把物体放到画轮廓线的层去
  183. print("+++" + obj.name);
  184.  
  185. }
  186.  
  187. }
  188.  
  189. }
  190. }

效果:

unity实现框选效果的更多相关文章

  1. JavaScript实现框选效果

    <html> <head> <title>region</title> <style> body { margin: 0; padding: ...

  2. vue封装一个简单的div框选时间的组件

    记录一下我前段时间封装的一个vue组件吧.技术需要积累,有时间我把我之前写的还不错的组件都开源出来.并尝试vue和react 两种方式的组件封装.今天简单写下鼠标框选div选中效果的封装吧. div框 ...

  3. [转]结合轮廓显示,实现完整的框选目标(附Demo代码)

    原地址:http://www.cnblogs.com/88999660/articles/2887078.html 几次看见有人问框选物体的做法,之前斑竹也介绍过,用画的框生成的视椎,用经典图形学的视 ...

  4. unity3d结合轮廓显示,实现完整的框选目标(附Demo代码)

    原地址:http://dong2008hong.blog.163.com/blog/static/469688272013111554511948/ 在unity里实现,其实很简单,因为有两个前提:1 ...

  5. jQuery实现全选效果【转】

    这是一段用jquery实现全选的代码,主要思路如下: 1.所有的复选框都有单击事件,所有效果都是在单击事件下实现的 2.全选复选框所实现的功能与其他复选选项实现的功能不同,所有在单击事件内做一个判断, ...

  6. Javascript实现鼠标框选元素后拖拽被框选的元素

    之前需要做一个框选元素后拖拽被框选中的元素功能,在网上找资料做了一些修改,基本达到了需要的效果,希望对也需要实现框选后拖拽元素功能的人有用. 页面加载后效果 框选后的内容可以拖拽,如下图: 代码下载

  7. ListView鼠标框选实现蓝色蒙板

    此问题留心已久,今日方悉心求之,记录心得. ListView控件,不论Delphi中的TListView还是c#中的ListView,在开启其MultiSelect属性时,鼠标框选只是显示框张,如下图 ...

  8. 原生js实现在表格用鼠标框选并有反选功能

    今天应同学要求,需要写一个像Excel那样框选高亮,并且实现框选区域实现反选功能.要我用原生js写,由于没什么经验翻阅了很多资料,第一次写文章希望各位指出不足!! 上来先建表 <div clas ...

  9. Cesium实现右键框选

    思路 1.先取消地图的右键事件 2.右键框选事件,屏幕坐标转为经纬度坐标 取消地图的右键事件 //此处容易犯一个错误:以为右键事件绑定了缩放功能,伪代码即 Cesium.MouseEvent.右键事件 ...

随机推荐

  1. VS2013 类向导 "异常来自 HRESULT:0x8CE0000B" 解决方法

    转自 http://blog.csdn.net/skyloveyue/article/details/52105912 我用使用了第二种方法: 改变项目的位置 将项目从原来D盘的位置(D:\proje ...

  2. OpenFlow, SDN, and NFV

    OpenFlow An open standard to innovative protocols in production networks provides a standardized hoo ...

  3. #warning Incomplete method implementation怎么修改?

    #warning Incomplete method implementation怎么修改?       各位朋友,我在做一个表格视图的例子,在tableview方法里总有几个warning:#war ...

  4. 如何设置ASP.NET页面的运行超时时间 (转载)

    全局超时时间 服务器上如果有多个网站,希望统一设置一下超时时间,则需要设置 Machine.config 文件中的 ExecutionTimeout 属性值.Machine.config 文件位于 % ...

  5. type和 #define

    1.#define INT8U unsigned char   :  用INT8U代替unsigned char 2.typedef typedef int size; 此声明定义了一个int的同义字 ...

  6. Zookeeper简介和安装(四)

    一.简介: Zookeeper是一个分布式协调服务,提供的服务如下: 命名服务:类似于DNS,但仅对于节点 配置管理:服务配置信息的管理 集群管理:Dubbo使用Zookeeper实现服务治理 分布式 ...

  7. 在CentOS7上安装MySQL5.7-YUM源方式

    获取RPM包 # wget https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm 列出RPM包里都有哪些文件 # ...

  8. Unity3D Errors And Fix

    Author Error: Shader warning in 'Custom/ShowAnimation': Not enough temporary registers, needs 9 (com ...

  9. wordpress | 网站访问速度优化方案(Avada)

    一.谷歌字体 原因: Wordpress系统默认使用谷歌字体,在国内谷歌域名被屏蔽,所以导致操作反应慢. 解决方法: 对于后台:找到Wordpress这个文件 /wp-includes/script- ...

  10. 编译升级至openssh7.6

    1.概述 目的:下载源码包(https://openbsd.hk/pub/OpenBSD/OpenSSH/portable/openssh-7.6p1.tar.gz),编译升级为openssh为7.6 ...