思路:

  在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的材质即可。

using UnityEngine;
using System.Collections;
using System.Collections.Generic; public class SelectObjects : MonoBehaviour
{ public List<GameObject> characters;
public Color rectColor = Color.green; private Vector3 start = Vector3.zero;//记下鼠标按下位置 // private Material rectMat = null;//画线的材质 不设定系统会用当前材质画线 结果不可控
public Material rectMat = null;//这里使用Sprite下的defaultshader的材质即可 private bool drawRectangle = false;//是否开始画线标志 // Use this for initialization void Start()
{ // rectMat = new Material("Shader \"Lines/Colored Blended\" {" +
//
// "SubShader { Pass { " +
//
// " Blend SrcAlpha OneMinusSrcAlpha " +
//
// " ZWrite Off Cull Off Fog { Mode Off } " +
//
// " BindChannels {" +
//
// " Bind \"vertex\", vertex Bind \"color\", color }" +
//
// "} } }");//生成画线的材质 rectMat.hideFlags = HideFlags.HideAndDontSave; rectMat.shader.hideFlags = HideFlags.HideAndDontSave;//不显示在hierarchy面板中的组合,不保存到场景并且卸载Resources.UnloadUnusedAssets不卸载的对象。 } void Update()
{ if (Input.GetMouseButtonDown())
{ drawRectangle = true;//如果鼠标左键按下 设置开始画线标志 start = Input.mousePosition;//记录按下位置 }
else if (Input.GetMouseButtonUp())
{ drawRectangle = false;//如果鼠标左键放开 结束画线
checkSelection(start,Input.mousePosition);
}
} void OnPostRender()
{//画线这种操作推荐在OnPostRender()里进行 而不是直接放在Update,所以需要标志来开启 if (drawRectangle)
{ Vector3 end = Input.mousePosition;//鼠标当前位置 GL.PushMatrix();//保存摄像机变换矩阵,把投影视图矩阵和模型视图矩阵压入堆栈保存 if (!rectMat) return; rectMat.SetPass();//为渲染激活给定的pass。 GL.LoadPixelMatrix();//设置用屏幕坐标绘图 GL.Begin(GL.QUADS);//开始绘制矩形 GL.Color(new Color(rectColor.r, rectColor.g, rectColor.b, 0.1f));//设置颜色和透明度,方框内部透明 //绘制顶点
GL.Vertex3(start.x, start.y, ); GL.Vertex3(end.x, start.y, ); GL.Vertex3(end.x, end.y, ); GL.Vertex3(start.x, end.y, ); GL.End(); GL.Begin(GL.LINES);//开始绘制线 GL.Color(rectColor);//设置方框的边框颜色 边框不透明 GL.Vertex3(start.x, start.y, ); GL.Vertex3(end.x, start.y, ); GL.Vertex3(end.x, start.y, ); GL.Vertex3(end.x, end.y, ); GL.Vertex3(end.x, end.y, ); GL.Vertex3(start.x, end.y, ); GL.Vertex3(start.x, end.y, ); GL.Vertex3(start.x, start.y, ); GL.End(); GL.PopMatrix();//恢复摄像机投影矩阵 } } //检测被选择的物体
void checkSelection(Vector3 start, Vector3 end)
{ Vector3 p1 = Vector3.zero; Vector3 p2 = Vector3.zero; if (start.x > end.x)
{//这些判断是用来确保p1的xy坐标小于p2的xy坐标,因为画的框不见得就是左下到右上这个方向的 p1.x = end.x; p2.x = start.x; } else { p1.x = start.x; p2.x = end.x; } if (start.y > end.y)
{ p1.y = end.y; p2.y = start.y; } else { p1.y = start.y; p2.y = end.y; } foreach (GameObject obj in characters)
{//把可选择的对象保存在characters数组里 Vector3 location = Camera.main.WorldToScreenPoint(obj.transform.position);//把对象的position转换成屏幕坐标 if (location.x < p1.x || location.x > p2.x || location.y < p1.y || location.y > p2.y || location.z < Camera.main.nearClipPlane || location.z > Camera.main.farClipPlane)//z方向就用摄像机的设定值,看不见的也不需要选择了 {
//disselecting(obj);//上面的条件是筛选 不在选择范围内的对象,然后进行取消选择操作,比如把物体放到default层,就不显示轮廓线了
print("---"+obj.name);
} else {
//selecting(obj);//否则就进行选中操作,比如把物体放到画轮廓线的层去
print("+++" + obj.name); } } }
}

效果:

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. MVC学习十四:MVC 路由 Route

    一.MVC路由(Route)是什么? MVC路由(Route)可以理解规定用户访问网站方式的配置文件,就例如:我们在访问普通页面时http://xxxx/web/xx.aspx,但在MVC中我们的访问 ...

  2. 解决MyEclipse JAVA EE无法识别Base64问题

    第一步:右击项目选择Build Path,选择Configure Build Path 第二步:点击JRE System Library选择右边的Edit 第三步:选择Alternate JRE,点击 ...

  3. Linux -- 用户篇

    Linux -- 用户与用户组 1.Linux 系统中有三种角色:所有者(用户),用户组与其他人,一张图可以说明用户与用户组的关系. 如图,某公司相当于一个用户组,该用户组下有A,B两个用户,用户拥有 ...

  4. angular动态绑定样式以及改变UI框架样式的方法

    一:angular动态绑定样式 举个栗子: <tr *ngFor="let dataTr of tableData;let i = index" [formGroupName ...

  5. GIT更新一其中一个提交版本

    有一小朋友刚才SVN转到GIT,最近老是咨询怎么才svn update -rXXXXX 在git其实也不麻烦,就是git checkout的事情,不管是分支还是TAG,都会有一个HASH版本号 1. ...

  6. mysql主从延迟复制

    需求描述 正常情况下我们是不会有刻意延迟从库的需求的,因为正常的线上业务自然是延迟越低越好.但是针对测试场景,业务上偶尔需要测试延迟场景下业务是否能正常运行. 解决方案 针对这种场景mysql有一个叫 ...

  7. Hibernate 事务不回滚

    问题:               这几天在做开发时,发现事务不回滚了,Service是用AOP加的事务,数据库是MySql, 表全部是InnoDB:   方法回滚是采用spring的手动回滚:   ...

  8. ActivatedRoute 当前激活的路由对象

    ActivatedRoute,当前激活的路由对象,主要用于保存路由,获取路由传递的参数. 一:传递参数的三种方式,以及ActivatedRoute获取他们的方式: 1.在查询参数中传递数据: /pro ...

  9. stm32串口发送数据复位 第一个数据丢失

    http://blog.csdn.net/kevinhg/article/details/40991655 STM32串口发送必须先检测状态,否则第一个字节无法发出,发送完毕,必须检测发送状态是否完成 ...

  10. Vue 生产环境部署

    简要:继上次搭建vue环境后,开始着手vue的学习;为此向大家分享从开发环境部署到生产环境(线上)中遇到的问题和解决办法,希望能够跟各位VUE大神学习探索,如果有不对或者好的建议告知下:*~*! 一. ...