why

The game screen is composed of multiple UI interfaces. When picking up UI controls in the scene, the outermost RectTransform control object is often selected first, regardless of whether this object is actually rendered or not, resulting in multiple selections to select the closest UI control. In addition, because Unity preferentially selects controls for the SelectionBase property, the pick button text will pick the button first.

To solve

Automatically pick up visual UI controls, Graphic controls, by capturing mouse clicks inside SceneView, as shown below:

limit

Try to use the pick Tool under Move Tool rather than Rect Tool, otherwise the correct controls may not be collected.

The source code

Gist.github.com/akof1314/be…

using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;

public class SceneViewPickUI{[InitializeOnLoadMethod]
    private static void Initialize()
    {
        SceneView.onSceneGUIDelegate += OnSceneGUIDelegate;
    }

    private static void OnSceneGUIDelegate(SceneView sceneView)
    {
        if(! sceneView.in2DMode) {return;
        }

        if (pick == null)
        {
            pick = new SceneViewPickUI();
        }
        pick.OnGUI();
    }

    private const string menuName = "Tools/Pick UI";

    [MenuItem(menuName, false, 0)]
    private static void ShowMenuPick()
    {
        if (pick == null)
        {
            pick = new SceneViewPickUI();
        }
        pick.SetUse();
    }

    private static SceneViewPickUI pick;
    private bool m_UsePick;
    private bool m_RectSelecting;
    private Vector2 m_SelectStartPoint;
    enum SelectionType { Normal, Additive, Invert }

    private SceneViewPickUI()
    {
        m_UsePick = EditorPrefs.GetBool("SceneViewPickUI".false);
        Menu.SetChecked(menuName, m_UsePick);
    }

    private void SetUse(){ m_UsePick = ! m_UsePick; EditorPrefs.SetBool("SceneViewPickUI", m_UsePick);
        Menu.SetChecked(menuName, m_UsePick);
    }

    private void OnGUI()
    {
        if(! m_UsePick) {return;
        }

        Handles.BeginGUI();
        var usePick = GUILayout.Toggle(m_UsePick, "Pick UI");
        if(usePick ! = m_UsePick) { SetUse(); } Handles.EndGUI();if(! m_UsePick) {return;
        }

        Event evt = Event.current;
        Vector2 mousePos = evt.mousePosition;
        int id = GUIUtility.GetControlID(FocusType.Passive);

        switch (evt.GetTypeForControl(id))
        {
            case EventType.Layout:
                HandleUtility.AddDefaultControl(id);
                break;

            case EventType.MouseDown:
                if (HandleUtility.nearestControl == id && evt.button == 0)
                {
                    GUIUtility.hotControl = id;
                    m_SelectStartPoint = mousePos;
                    m_RectSelecting = false;
                }
                break;
            case EventType.MouseDrag:
                if (GUIUtility.hotControl == id)
                {
                    if(! m_RectSelecting && (mousePos - m_SelectStartPoint).magnitude >6f)
                    {
                        m_RectSelecting = true; }}break;
            case EventType.MouseUp:
                if (GUIUtility.hotControl == id && evt.button == 0)
                {
                    GUIUtility.hotControl = 0;
                    if (m_RectSelecting)
                    {
                        m_RectSelecting = false;
                    }
                    else
                    {
                        SelectionType selectionType = SelectionType.Normal;
                        if (evt.shift)
                        {
                            selectionType = SelectionType.Additive;
                        }
                        else if (EditorGUI.actionKey)
                        {
                            selectionType = SelectionType.Invert;
                        }

                        if(UpdateSelection(selectionType)) { evt.Use(); }}}break; }}private bool UpdateSelection(SelectionType type)
    {
        var overlapped = new List<GameObject>();
        do
        {
            var go = HandleUtility.PickGameObject(Event.current.mousePosition, false, overlapped.ToArray());
            if(! go) {break;
            }

            var rt = go.GetComponent<RectTransform>();
            if(! rt) {break;
            }

            var mg = go.GetComponent<Graphic>();
            if (mg && mg.color.a > 0    // The color itself is opaque
                   && mg.canvasRenderer.materialCount > 0   // Components are not disabled
                   && mg.canvasRenderer.GetInheritedAlpha() > 0 // Alpha caused by CanvasGroups is not 0
                   / / &&! Go.getcomponent 
      
       () // Empty grid is not selected
      
                   )
            {
                //Debug.LogWarning(go, go);
                switch (type)
                {
                    case SelectionType.Additive:
                        {
                            List<Object> newSelection = new List<Object>();
                            newSelection.AddRange(Selection.objects);
                            newSelection.Add(go);
                            Selection.objects = newSelection.ToArray();
                        }

                        break;
                    case SelectionType.Invert:
                        {
                            List<Object> newSelection = new List<Object>();
                            newSelection.AddRange(Selection.objects);
                            if (newSelection.Contains(go))
                            {
                                newSelection.Remove(go);
                            }
                            else
                            {
                                newSelection.Add(go);
                            }
                            Selection.objects = newSelection.ToArray();
                        }
                        break;
                    case SelectionType.Normal:
                        Selection.activeObject = go;
                        break;
                }

                return true;
            }

            if (overlapped.Count > 0 && overlapped[overlapped.Count - 1] == go)
            {
                break;
            }

            overlapped.Add(go);
        } while (true);
        return false; }}Copy the code