思路:

  在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. 【题解】洛谷P3953 [NOIP2017TG] 逛公园(记忆化搜索+SPFA)

    题目来源:洛谷P3953 思路 先用SPFA求一遍最短路 在求最短路的同时可以把所有点到终点的最短路求出来 dis数组 注意要反向SPFA  因为从起点开始可能会走到一些奇怪的路上导致时间负责度增加 ...

  2. HDU 2031 进制转换(10进制转R进制)

    传送门: http://acm.hdu.edu.cn/showproblem.php?pid=2031 进制转换 Time Limit: 2000/1000 MS (Java/Others)    M ...

  3. Matplotlib中中文不显示问题

    我们在使用jupter进行数据分析的时候,会接触到Matplotlib这个库,它是用来进行可视化数据分析的,在一个图中,我们常常会加入一些中文来进行说明.当我们加入中文的时候会出现下图所示的样子: 可 ...

  4. one or more listeners failed to start问题解决思路

    今日搭建一个web应用的时候总是遇到tomcat报错:one or more listeners failed to start. Full detail balabale....而且还没有其他提示, ...

  5. 为什么我们需要DTO?

    最近在写代码时突然产生了这个疑惑,我们为什么需要DTO进行数据传输呢? 要了解DTO首先我们要知道什么是DAO,DAO就是数据库的一个数据模型,是一个类文件里面存储着数据库的字段及其getter&am ...

  6. MySQL 开启事件 使用定时器调用存储过程

      mysql定时器是系统给提供了event,而oracle里面的定时器是系统给提供的job.废话少说,下面创建表:create table mytable (id int auto_incremen ...

  7. Django学习之mysql结果显示

    背景:向数据库添加相同名字的用户 上节可知,在查询某个用户信息时,只能查看到行数但不能查看结构性信息. fetchone()函数可以但仅可逐个查看结构性信息.查不到信息将以None替补. fetchA ...

  8. rails应用页面导出为pdf文档

    1.下载安装wkhtmltox https://wkhtmltopdf.org/downloads.html   2.gemfile添加 gem 'pdfkit' #页面导出pdf gem 'wkht ...

  9. 863. All Nodes Distance K in Binary Tree

    /** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode ...

  10. linux 下安装 Cisco Packet Tracer 7.11以及一些注意

    https://blog.csdn.net/qq_35882901/article/details/77652571 https://linux.cn/article-5576-1.html 开启登录 ...