Unity 编辑器-监听创建控件,prefab创建或添加组件的自动处理⭐
拓展控件
- 需求
- 解决方案
- 方案
需求
比如我想在添加Text时,自动添加一个脚本,用于处理多语言。在添加图片时,自动去掉raycast的勾选以节约性能损耗
解决方案
方案
ObjectFactory.componentWasAdded
用于监听组件的添加事件
using TMPro;
using UnityEngine;
using UnityEditor;
using UnityEngine.UI;
using UnityEngine.EventSystems;
/// <summary>
/// Inspector面板添加组件回调
/// </summary>
[InitializeOnLoad]
public class InspectorAddComponent
{static InspectorAddComponent(){//监听组件添加事件ObjectFactory.componentWasAdded += ComponentWasAdded;}private static void ComponentWasAdded(Component com){switch (com.GetType().ToString()){case "UnityEngine.UI.Image":ComponentOptimizing.OptimizingImage(com as Image);break;case "UnityEngine.UI.Text":ComponentOptimizing.OptimizingText(com as Text);break;case "UnityEngine.UI.Button":ComponentOptimizing.OptimizingButton(com as Button);break;case "UnityEngine.UI.Mask":ComponentOptimizing.OptimizingMask(com as Mask);break;case "TMPro.TextMeshProUGUI":ComponentOptimizing.OptimizingTmp(com as TextMeshProUGUI);break;}}
}
using TMPro;
using Unity.VisualScripting;
using UnityEditor;
using UnityEditor.Events;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;/// <summary>
/// 组件优化设置
/// </summary>
public class ComponentOptimizing
{#region Imagepublic static void OptimizingImage(Image image){//如果当前图片不是按钮,取消勾选RaycastTargetif (image.gameObject.GetComponent<Button>() == null){image.raycastTarget = false;}}#endregion#region TextMeshProUGUIpublic static void OptimizingTmp(TextMeshProUGUI tmp){if (tmp.gameObject.GetComponent<MaskableGraphic>() == null ){tmp.raycastTarget = false;}if (tmp.GetComponent<DictionaryText>() == null){tmp.AddComponent<DictionaryText>();}}#endregion#region Textpublic static void OptimizingText(Text text){if (text.gameObject.GetComponent<MaskableGraphic>() == null){text.raycastTarget = false;}//是否支持富文字框架,默认不支持,有需求再手动勾选text.supportRichText = false;if (text.GetComponent<DictionaryText>() == null){text.AddComponent<DictionaryText>();}}#endregion#region Buttonpublic static void OptimizingButton(Button button){//判断需要添加button组件的物体是否有继承自MaskableGraphic的组件,有的话就勾选RaycastTargetif (button.gameObject.GetComponent<MaskableGraphic>() != null){button.gameObject.GetComponent<MaskableGraphic>().raycastTarget = true;}if (button.GetComponent<ClickSound>() == null){var btnE = button.AddComponent<ClickSound>();button.onClick.AddListener(btnE.OnPlaySound);AddListener(button, btnE.OnPlaySound);}}private static void AddListener(Button button, UnityAction e){// 获取或创建自定义序列化对象和属性SerializedObject serializedButton = new SerializedObject(button);// 将新创建的 UnityEvent 添加到 Button 的 OnClick 事件中UnityEventTools.AddVoidPersistentListener(button.onClick, e);// 应用所有更改并重新绘制 Inspector 视图serializedButton.ApplyModifiedProperties();}#endregion#region Maskpublic static void OptimizingMask(Mask mask){//判断需要添加mask组件的物体是否有继承自MaskableGraphic的组件,有的话就勾选RaycastTargetif (mask.gameObject.GetComponent<MaskableGraphic>() != null){mask.gameObject.GetComponent<MaskableGraphic>().raycastTarget = true;}}#endregion
}


如图,inspector 面板和场景中创建的所有控件,几乎都能触发这个回调。
或者说所有使用到ObjectFactory.AddComponent
方法添加脚本的都能触发这个回调。

值得注意的是TextmeshoPro.。测试发现TextMeshProUGU 部分控件不能触发事件


查看源码可发现,text - TextMeshPro
控件使用的是ObjectFactory.AddComponent
,而Button - TextMeshPro
使用的是GameObject.AddComponent
如果需要修改,可以把TMP
的package
包从PackageManager
中挪出来,改为本地Package