今天研究了一下框选功能,这是个很老旧的功能了 ,网上有很多资料,不过看了几个发现都是旧版本的,新版本有些东西要改动一下才好使,就改了改,写个博客纪录一下,
还是大概说一下思路吧,
1.鼠标按下时记录鼠标点下的屏幕坐标,通过unity提供的Camera的方法 WorldToScreenPoint,将待选物体由世界坐标转屏幕坐标.当然反过来也是一样的
2.第二就是比较一个点是否在一个范围内 这个很好理解,比xy轴就行了
3.屏幕上要画线 刷出来拖动的范围,用的是GL划线,需要一个特定的shader 这个也是之前老版本的代码不支持的地方
先上效果图

然后上代码
这个因为有OnPostRender方法,脚本需要挂相机上才框选范围可以生效;
这个因为有OnPostRender方法,脚本需要挂相机上才框选范围可以生效;
这个因为有OnPostRender方法,脚本需要挂相机上才框选范围可以生效
using UnityEngine;
public class DrawRect : MonoBehaviour {
private bool drawing;
private Material rectMat;
private Color rectColor = Color.green;
private Vector2 startPosition = Vector2.zero;
private Vector2 endPosition = Vector2.zero;
void Start()
{
rectMat = new Material(Shader.Find("Lines/Colored Blended"));
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
drawing = true;
// 设置开始位置
startPosition = Input.mousePosition;
CubeManager.Instance.BeginDraw();
}
if (Input.GetMouseButtonUp(0))
{
drawing = false;
}
}
// 该方法为系统函数,需将此脚本挂载到Camera下才能执行。
void OnPostRender()
{
if (drawing)
{
GL.PushMatrix();
if (!rectMat)
return;
endPosition = Input.mousePosition; // 设置结束位置
CubeManager.Instance.Drawing(startPosition, endPosition);
rectMat.SetPass(0);
GL.LoadPixelMatrix();
GL.Begin(GL.QUADS);
GL.Color(new Color(rectColor.r, rectColor.g, rectColor.b, 0.1f ));
GL.Vertex3(startPosition.x, startPosition.y, 0);
GL.Vertex3(endPosition.x, startPosition.y, 0);
GL.Vertex3(endPosition.x, endPosition.y, 0);
GL.Vertex3(startPosition.x, endPosition.y, 0);
GL.End();
GL.Begin(GL.LINES );
GL.Color(rectColor );
GL.Vertex3(startPosition.x, startPosition.y, 0);
GL.Vertex3(endPosition.x, startPosition.y, 0);
GL.Vertex3(endPosition.x, startPosition.y, 0);
GL.Vertex3(endPosition.x, endPosition.y, 0);
GL.Vertex3(endPosition.x, endPosition.y, 0);
GL.Vertex3(startPosition.x, endPosition.y, 0);
GL.Vertex3(startPosition.x, endPosition.y, 0);
GL.Vertex3(startPosition.x, startPosition.y, 0);
GL.End();
GL.PopMatrix();
}
}
}这个脚本随便挂一个地方 拖个盒子和两个材质球就好了
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class CubeManager : MonoBehaviour {
private static CubeManager instance;
public static CubeManager Instance
{
get
{
return instance;
}
}
public GameObject prefab;
public int count = 10;
public Material originMat;
public Material outlineMat;
private List<MeshRenderer> meshRendererList;
void Awake()
{
instance = this;
}
// Use this for initialization
void Start () {
meshRendererList = new List<MeshRenderer>();
// 创建物体
for ( int i = 0; i < count; i++ )
{
GameObject go = GameObject.Instantiate( prefab ) as GameObject;
go.name = (i + 1).ToString();
go.transform.parent = transform;
go.transform.position = new Vector3( Random.Range( -10, 10 ), 0, Random.Range( -10, 10 ) );
meshRendererList.Add( go.GetComponent<MeshRenderer>() );
}
originMat = meshRendererList[0].material;
}
public void BeginDraw()
{
var item = meshRendererList.GetEnumerator();
while (item.MoveNext())
{
item.Current.material = originMat;
}
}
public void Drawing(Vector2 point1, Vector2 point2)
{
Vector3 p1 = Vector3.zero;
Vector3 p2 = Vector3.zero;
if (point1.x > point2.x)
{
p1.x = point2.x;
p2.x = point1.x;
}
else
{
p1.x = point1.x;
p2.x = point2.x;
}
if (point1.y > point2.y)
{
p1.y = point2.y;
p2.y = point1.y;
}
else
{
p1.y = point1.y;
p2.y = point2.y;
}
var item = meshRendererList.GetEnumerator();
while (item.MoveNext())
{
Vector3 position = Camera.main.WorldToScreenPoint(item.Current.transform.position);
if (position.x > p1.x && position.y > p1.y
&& position.x < p2.x && position.y < p2.y )
{
item.Current.material = outlineMat;
}
else
{
item.Current.material = originMat;
}
}
}
}场景中截图

下边是GL的材质shader
Shader "Lines/Colored Blended"
{
SubShader
{
Pass
{
Blend SrcAlpha OneMinusSrcAlpha
ZWrite Off Cull Off Fog { Mode Off }
BindChannels
{
Bind "vertex", vertex Bind "color", color
}
}
}
}
最后也把原来的博客连接发一下,不能那么无耻的就偷别人的代码哈哈修改前的原文
版权声明:本文为qq_35080168原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。