-  场景准备 
  
-  准备一张框选背景图 
 导入到unity之后,修改 Texture Type 为 Sprite,(根据图片需要)在 Sprite Editor 中 编辑 九宫格格式。图片样式的不一致,设置的九宫格格式也不一致。本例中虚线部分需要等距离平铺,所以如下设置即可满足要求。
  
-  Image组件设置 
 pivot的正确设置很重要,否则当我们更新Image尺寸的时候,尺寸更新了,不跟随鼠标
 由于我选择的框选图片背景是虚线格式的,虚线部分想等距平铺,所以这里Image Type选择Tiled即可。
 然后添加boxSelection脚本。实现框选功能。
  
 这里是在Update里面通过获取鼠标当前操作,更新image尺寸实现的框选,在鼠标松开时,检测3d区域内物体是否在框选范围内即可。实现方式非常简单易懂,且性能损耗比较小。
	public class BoxSelection : MonoBehaviour
    {
        public Material normalMat;
        public Material highlightMat;
        public Transform root;
        
        private RectTransform selectionBoxRectTrans;
        private Canvas canvas;
        private bool onDrawingRect;
        private Vector2  startPoint;
        private Vector2  endPoint;
        private Selector selector;
        
        private void Start()
        {
            canvas = GetComponentInParent<Canvas>();
            selectionBoxRectTrans = GetComponent<RectTransform>();
        }
        void Update()
        {
            if (Input.GetMouseButtonDown(0))
            {
                onDrawingRect = true;
                startPoint = Input.mousePosition;
            }
            if (onDrawingRect)
            {
                UpdateSelection();
            }
            if (onDrawingRect && Input.GetMouseButtonUp(0))
            {
                endPoint = Input.mousePosition;
                onDrawingRect = false;
                ClearSelection();
                selector = new Selector(startPoint, endPoint);
                Selection(selector);
            }
        }
        
        void UpdateSelection()
        {
            Vector2 currentPoint = Input.mousePosition;
            float minX = Mathf.Min(currentPoint.x, startPoint.x);
            float minY = Mathf.Min(currentPoint.y, startPoint.y);
            float maxX = Mathf.Max(currentPoint.x, startPoint.x);
            float maxY = Mathf.Max(currentPoint.y, startPoint.y);
            selectionBoxRectTrans.position = new Vector3(minX, minY, 0);
            selectionBoxRectTrans.sizeDelta = new Vector2(Mathf.Abs(maxX - minX) / canvas.scaleFactor, Mathf.Abs(maxY - minY) / canvas.scaleFactor);
        }
        void ClearSelection()
        {
            selectionBoxRectTrans.sizeDelta = Vector2.zero;
        }
     
        void Selection(Selector selector)
        {
            foreach(Transform child in root)
            {
                Vector3 screenPos = Camera.main.WorldToScreenPoint(child.position);
                if (screenPos.x > selector.Xmin && screenPos.x < selector.Xmax && screenPos.y > selector.Ymin && screenPos.y < selector.Ymax)
                {
                    child.GetComponent<MeshRenderer>().material = highlightMat;
                }
                else
                {
                    child.GetComponent<MeshRenderer>().material = normalMat;
                }
            }
        }
        
        private class Selector
        {
            public float Xmin;
            public float Xmax;
            public float Ymin;
            public float Ymax;
     
            //构造函数,在创建选定框时自动计算Xmin/Xmax/Ymin/Ymax
            public Selector(Vector3 start, Vector3 end)
            {
                Xmin = Mathf.Min(start.x, end.x);
                Xmax = Mathf.Max(start.x, end.x);
                Ymin = Mathf.Min(start.y, end.y);
                Ymax = Mathf.Max(start.y, end.y);
            }
        }
    }
当然,也可以不使用Image组件,我们可以通过GL绘制的方式,通过OnGUI或者OnPostRender的方法绘制【框】。不需要九宫格图片,将脚本挂载在Camera上即可。
 // 画框代码
        public Color GLRectColor;
        public Color GLRectEdgeColor;
        private bool onDrawingRect;
        private Vector3 startPoint;
        private Vector3 currentPoint;
        private Vector3 endPoint;
      
        private void Start()
        {
            InitMaterial();
        }
        
        protected Material lineMaterial;
        protected void InitMaterial()
        {
            if (!lineMaterial)
            {
                // Unity3d使用该默认的Shader作为线条材质    
                Shader shader = Shader.Find("Hidden/Internal-Colored");
                lineMaterial = new Material(shader);
                lineMaterial.hideFlags = HideFlags.HideAndDontSave;
                // 开启 alpha blending    
                lineMaterial.SetInt("_SrcBlend", (int)BlendMode.SrcAlpha);
                lineMaterial.SetInt("_DstBlend", (int)BlendMode.OneMinusSrcAlpha);
                // 开启背面遮挡    
                lineMaterial.SetInt("_Cull", (int)CullMode.Off);
                // Turn off depth writes    
                lineMaterial.SetInt("_ZWrite", 0);
                lineMaterial.SetInt("_ZTest", (int)CompareFunction.Always);
            }
        }
		void Update()
        {
            if (Input.GetMouseButtonDown(0))
            {
                onDrawingRect = true;
                startPoint = Input.mousePosition;
            }
            if (Input.GetMouseButtonUp( 0 ) )
            {
                onDrawingRect = false;
            }
        }
        
		void OnGUI()
        {
            if (onDrawingRect)
            {
            	// GL线条材质
                if (!lineMaterial)
                    return;
                currentPoint = Input.mousePosition;
        
        		// 根据起始点和现在鼠标位置,便可以获取框的四个点的坐标!
                Vector3 p0 = new Vector3(startPoint.x, Screen.height - startPoint.y, 0);
                Vector3 p1 = new Vector3(currentPoint.x, Screen.height - startPoint.y, 0);
                Vector3 p2 = new Vector3(currentPoint.x, Screen.height - currentPoint.y, 0);
                Vector3 p3 = new Vector3(startPoint.x, Screen.height - currentPoint.y, 0);
        
                lineMaterial.SetPass(0);
        
                GL.PushMatrix();
                // GL.LoadPixelMatrix();
                
                /*------第一步,绘制矩形------*/
                GL.Begin(GL.QUADS);
                GL.Color(GLRectColor); // 自己设置颜色
                GL.Vertex(p0);
                GL.Vertex(p1);
                GL.Vertex(p2);
                GL.Vertex(p3);
                GL.End();
        
                /*------第二步,绘制矩形的边框------*/
                GL.Begin(GL.LINES); 
                GL.Color(GLRectEdgeColor); // 自己设置颜色
                
                GL.Vertex(p0);
                GL.Vertex(p1);
        
                GL.Vertex(p1);
                GL.Vertex(p2);
        
                GL.Vertex(p2);
                GL.Vertex(p3);
        
                GL.Vertex(p3);
                GL.Vertex(p0);
                GL.End();
        
                GL.PopMatrix();
            }
        }



















