思路:

  在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. Java中Class类及用法

    Java中Class类及用法 Java程序在运行时,Java运行时系统一直对所有的对象进行所谓的运行时类型标识,即所谓的RTTI.这项信息纪录了每个对象所属的类.虚拟机通常使用运行时类型信息选准正确方 ...

  2. python查看微信消息撤回

    准备环境 python语言环境 python解释器-pycharm itchat介绍 itchat是一个开源的微信个人号接口,通过itchat可以实现微信(好友或微信群)的信息处理,包括文本.图片.小 ...

  3. 在网页中使用Markdown

    在网站中使用markdown有两种方式,一种是通过后端(php等)把markdown语法文本转换为html代码,输出到浏览器:另一种是通过javascript代码直接在浏览器中转换. 我在这里使用的是 ...

  4. 安装sqlserver2016出现的错误

    今天安装sharepoint 2016,projectserver 2016,在安装sqlserver2016的时候突然报错了,提示需要安装oracle java se, Rule “Oracle J ...

  5. 轻量ORM-SqlRepoEx (七)AspNetCore应用

    ORM-SqlRepoEx 是 .Net平台下兼容.NET Standard 2.0,一个实现以Lambda表达式转转换标准SQL语句,使用强类型操作数据的轻量级ORM工具,在减少魔法字串同时,通过灵 ...

  6. systemd的新特性及常见的systemd unit类型分析

    systemd概述 )systemd是一种新的linux系统服务管理器,用于替换init系统,能够管理系统启动过程和系统服务,一旦启动起来,就将监管整个系统.在centos7系统中,PID1被syst ...

  7. Canvas状态的保存与恢复

    Canvas的API提供了save()和restore()的方法,用于保存及恢复当前canvas绘图环境的所有属性. save()与restore()方法可以嵌套调用 save()方法将当前绘图环境压 ...

  8. java端连接zookeeper出现unknowHostException错误

    连接zookeeper出现异常:unknowHostException 出现这种错误一开始以为是zookeeper的配置文件出了问题,所以一直在找配置文件的问题,但是zookeeper在虚拟机里面是可 ...

  9. python学习笔记:第19天 类的约束、异常、MD5和logging

    目录 一.类的约束 二.异常处理: 三.MD5加密 四.日志(logging模块) 一.类的约束 真正写写项目的代码时都是多人协作的,所以有些地方需要约束程序的结构.也就是说,在分配任务之前就应该把功 ...

  10. python学习笔记:第18天 面向对象04-反射

    目录 issubclass和isinstance 区分函数和方法 反射 issubclass和isinstance issubclass:可以判断一个类是否另一个类的子类. # issubclass ...