[UNITY二三事_001] RaycastTarget 编辑器
程序员文章站
2022-07-08 17:36:16
目录整活代码废话整活RaycastTarget是Graphic类型的组件的一个成员, 点击之类的事件会发射射线查找开启了RaycastTarget的Graphic对象,并且排序获得最前面的Graphic,而这个功能默认是开启的…会导致奇怪的遮挡问题, 比如某个按钮点击不了开启太多RaycastTarget也会导致性能问题.因此我做了一个编辑器将当前场景(或预制体模式)下的所有开启了RaycastTarget的Graphic对象可视化,并且在EditorWindow中列举,可快速选择对象,开关R...
整活
RaycastTarget是Graphic类型的组件的一个成员, 点击之类的事件会发射射线查找开启了RaycastTarget的Graphic对象,并且排序获得最前面的Graphic,而这个功能默认是开启的…
- 会导致奇怪的遮挡问题, 比如某个按钮点击不了
- 开启太多RaycastTarget也会导致性能问题.
因此我做了一个编辑器将当前场景(或预制体模式)下的所有开启了RaycastTarget的Graphic对象可视化,并且在EditorWindow中列举,可快速选择对象,开关RaycastTarget功能.
这个想法来自雨松MOMO: UGUI研究院之有效解决RaycastTarget勾选过多的烦恼(二十三), 我只是在这个基础上改进了工作流程.
代码
- 注册 SceneView.duringSceneGui 委托
- 获得当前场景/预制体编辑模式中所有的Graphic对象
- 按Root分类
- 在Scene窗口中绘制开启了RaycastTarget的Graphic对象
- OnGUI中绘制EditorWindow
using UnityEngine;
using System.Collections.Generic;
using Sirenix.Utilities.Editor;
using UnityEditor;
using UnityEditor.Experimental.SceneManagement;
using UnityEngine.UI;
namespace XFrameworkEditor
{
/// <summary>
/// 雨松MOMO: https://www.xuanyusong.com/archives/4291
/// Unity会对所有勾选RaycastTarget的组件发出射线, 然后在排序找到最前面的。所以RaycastTarget越少越好
/// </summary>
public class RaycastTargetEditorWindow : EditorWindow
{
static Vector3[] _fourCorners = new Vector3[4];
private static Graphic[] _graphics;
private static bool _inited = false;
private static Dictionary<GameObject, List<Graphic>> _rootToGraphics = new Dictionary<GameObject, List<Graphic>>();
[MenuItem("功能列表/UI RaycastTarget编辑器 %F11")]
static void ShowWindow()
{
var window = (RaycastTargetEditorWindow)EditorWindow.GetWindow(typeof(RaycastTargetEditorWindow), false, "UI RaycastTarget编辑器", true);
window.Show();
}
/// <summary>
/// 绘制编辑器
/// </summary>
private void OnGUI()
{
var selectGo = Selection.activeGameObject;
GUILayout.BeginVertical();
foreach (var rootToGraphics in _rootToGraphics)
{
GUILayout.Label(rootToGraphics.Key.name, SirenixGUIStyles.BoldLabel);
foreach (var graphic in rootToGraphics.Value)
{
var currentGraphicGo = graphic.gameObject;
var selectThis = currentGraphicGo == selectGo;
if (selectThis)
GUILayout.BeginHorizontal(GUI.skin.box);
else
GUILayout.BeginHorizontal();
if (graphic.raycastTarget)
GUI.color = Color.white;
else
GUI.color = Color.white * 0.7f;
var newRaycastTargetState = GUILayout.Toggle(graphic.raycastTarget, "", GUILayout.Width(15));
if (newRaycastTargetState != graphic.raycastTarget)
{
Undo.RecordObject(graphic, "Graphic RaycastTarget");
graphic.raycastTarget = newRaycastTargetState;
EditorUtility.SetDirty(graphic);
}
var currentContent = $"{currentGraphicGo.name} ({graphic.GetType().Name})";
if (GUILayout.Button(currentContent, SirenixGUIStyles.Button))
Selection.activeGameObject = currentGraphicGo;
GUILayout.EndHorizontal();
GUILayout.Space(5);
}
GUILayout.Space(20);
}
GUILayout.EndVertical();
GUI.color = Color.white;
}
private void Update()
{
if (!_inited)
{
_inited = true;
SceneView.duringSceneGui -= OnSceneGUI;
SceneView.duringSceneGui += OnSceneGUI;
}
}
private void OnInspectorUpdate()
{
Repaint();
}
private void OnDestroy()
{
SceneView.duringSceneGui -= OnSceneGUI;
_inited = false;
}
/// <summary>
/// 获得当前场景的Graphics数据
/// </summary>
private static void OnSceneGUI(SceneView view)
{
var stage = PrefabStageUtility.GetCurrentPrefabStage();
if (stage != null)
_graphics = stage.FindComponentsOfType<Graphic>();
else
_graphics = GameObject.FindObjectsOfType<Graphic>(true);
SortGraphics();
DrawGraphics();
}
/// <summary>
/// 在编辑器中绘制Graphics轮廓
/// </summary>
private static void DrawGraphics()
{
Handles.color = Color.red;
foreach (Graphic g in _graphics)
{
if (g.raycastTarget)
{
var rectTransform = g.transform as RectTransform;
rectTransform.GetWorldCorners(_fourCorners);
for (int i = 0; i < 4; i++)
Handles.DrawLine(_fourCorners[i], _fourCorners[(i + 1) % 4]);
}
}
Handles.color = Color.white;
}
private static void SortGraphics()
{
_rootToGraphics.Clear();
foreach (var graphic in _graphics)
{
var rootGo = graphic.transform.root.gameObject;
if (!_rootToGraphics.ContainsKey(rootGo))
_rootToGraphics.Add(rootGo, new List<Graphic>());
_rootToGraphics[rootGo].Add(graphic);
}
}
}
}
废话
平时写点小东西,也就图一乐,大多数都是不能拿到生产上用的低能工具,但是相对来说开发效率高…稍微有点用的东西就写到博客里吧,分享一下,整理一下思路什么的.该睡了,又双叒叕熬夜了…
本文地址:https://blog.csdn.net/Jamesika/article/details/107588494