unity在project中点击某个节点时,会点到那些隐藏的节点,但是我们一般只是想获取能看到的那个,每次都要点半天才能找到,很麻烦。因此搞了这个工具,直接忽略隐藏节点获取鼠标点击位置的物体,方便多了。
使用方法:运行时在game窗口按下shift+alt+Q(不用打开窗口),可获取到鼠标点击会点到的物体。
如果打开了工具窗口,可以看到所有物体。窗口有两个选项【忽略隐藏的物体】【忽略raycast=false的物体】,作用就是名字,不多赘述了。
【当前相应事件的物体】就是点击会触发那个组件。
下面的列表指出所有可被点击的物体。
如果不忽略raycast能点到图片等等。
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class GetAllClickGameObjectWindow : EditorWindow
{
private string helpStr =
@"按下shitf+alt+q,会获取当前鼠标下的所有UI物体。
请在运行模式下使用。
请在Game窗口中使用。";
public bool ignoreHide = true; //忽略隐藏的物体
public bool ignoreRaycast = false; //忽略raycast target=false的物体
private GameObject currentSelect = null; //当前鼠标可点击到的物体
private GameObject currentClick = null; //当前相应点击事件的物体
private List<GameObject> gos //在鼠标下所有物体
= new List<GameObject>();
private Vector2 scrolPos;
private void OnGUI()
{
GUILayout.BeginHorizontal();
if (GUILayout.Button("打开文档"))
{
EditorGUILayout.HelpBox(helpStr, MessageType.Info);
//这里是项目文档链接,不放出来了
Help.BrowseURL("https://www.baidu.com/");
}
GUILayout.EndHorizontal();
ignoreHide = EditorGUILayout.Toggle("忽略隐藏的物体", ignoreHide);
ignoreRaycast = EditorGUILayout.Toggle("忽略raycast=false的物体", ignoreRaycast);
EditorGUILayout.ObjectField("当前直接点击的物体", currentSelect, typeof(GameObject), false);
EditorGUILayout.ObjectField("当前相应事件的物体", currentClick, typeof(GameObject), false);
GUILayout.Space(20);
GUILayout.Label("以下为所有物体");
scrolPos = GUILayout.BeginScrollView(scrolPos);
for (int i = 0; i < gos.Count; i++)
{
EditorGUILayout.ObjectField(gos[i], typeof(GameObject), false);
}
GUILayout.EndScrollView();
}
public void Refresh()
{
MyGetPointOverUI();
currentSelect = FindFirstRaycast(gos);
currentClick = ExecuteEvents.GetEventHandler<IEventSystemHandler>(currentSelect);
Repaint();
}
public void MyGetPointOverUI()
{
gos = GetPointOverUI(ignoreHide, ignoreRaycast);
}
private GameObject FindFirstRaycast(List<GameObject> gos)
{
if (gos == null || gos.Count < 1) return null;
return gos[0];
}
[MenuItem("Tools/UI节点选择工具")]
public static void GetWindow()
{
var window = GetWindow(typeof(GetAllClickGameObjectWindow)) as GetAllClickGameObjectWindow;
window.titleContent = new GUIContent("UI节点选择工具");
window.Show();
}
private static double lastQuickSelectTime = 0;
private static double quickSelectGap = 0.2f;
//不打开窗口直接选中
[MenuItem("Tools/用UI节点选择工具,这个没用 #&q")]
public static void QuickSelect()
{
GetAllClickGameObjectWindow window = null;
if (HasOpenInstances<GetAllClickGameObjectWindow>())
{
window = EditorWindow.GetWindow<GetAllClickGameObjectWindow>("UI节点选择工具", false);
}
bool ignoreHide = true, ignoreRaycast = false;
if (window != null)
{
ignoreHide = window.ignoreHide;
ignoreRaycast = window.ignoreRaycast;
}
if (Time.realtimeSinceStartup - lastQuickSelectTime < quickSelectGap)
return;
lastQuickSelectTime = Time.realtimeSinceStartup;
var result = GetPointOverUI(ignoreHide, ignoreRaycast);
var index = result.FindIndex(p => p?.gameObject == Selection.activeGameObject);
index = (index + 1) % result.Count;
if (0 <= index && index < result.Count)
{
Selection.activeGameObject = result[index].gameObject;
}
if (window != null) window.Refresh();
}
public static List<GameObject> GetPointOverUI(bool ignoreHide, bool ignoreRaycast)
{
Canvas[] canvasArray = FindObjectsOfType<Canvas>();
List<Graphic> result = new List<Graphic>();
for (int i = 0; i < canvasArray.Length; i++)
{
var canvas = canvasArray[i];
Graphic[] graphics = canvas.GetComponentsInChildren<Graphic>(!ignoreHide);
graphics.ToList().ForEach(p =>
{
//Debug.Log(p);
if (ignoreRaycast && !p.raycastTarget) return;
var pos = Input.mousePosition;
Vector3[] ans = new Vector3[4];
p.rectTransform.GetWorldCorners(ans);
Vector3 min = ans[0], max = ans[2];
if (canvas.renderMode == RenderMode.ScreenSpaceCamera)
{
min = canvas.worldCamera.WorldToScreenPoint(min);
max = canvas.worldCamera.WorldToScreenPoint(max);
}
if (min.x <= pos.x && pos.x <= max.x && min.y <= pos.y && pos.y <= max.y)
{
result.Add(p);
}
});
}
if (result.Count <= 0) return null;
result.Sort((g1, g2) => g2.depth.CompareTo(g1.depth));
return result.Select(p => p.gameObject).ToList();
}
}