Unity 编辑器-监听创建控件,prefab创建或添加组件的自动处理⭐

拓展控件

需求

比如我想在添加Text时,自动添加一个脚本,用于处理多语言。在添加图片时,自动去掉raycast的勾选以节约性能损耗

解决方案

方案

ObjectFactory.componentWasAdded 用于监听组件的添加事件

csharp 复制代码
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;
        }
    }
}
csharp 复制代码
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 Image

    public static void OptimizingImage(Image image)
    {
        //如果当前图片不是按钮,取消勾选RaycastTarget
        if (image.gameObject.GetComponent<Button>() == null)
        {
            image.raycastTarget = false;
        }
    }

    #endregion

    #region TextMeshProUGUI

    public static void OptimizingTmp(TextMeshProUGUI tmp)
    {
        if (tmp.gameObject.GetComponent<MaskableGraphic>() == null )
        {
            tmp.raycastTarget = false;
        }
        
        if (tmp.GetComponent<DictionaryText>() == null)
        {
            tmp.AddComponent<DictionaryText>();
        }
    }

    #endregion
    #region Text

    public 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 Button

    public static void OptimizingButton(Button button)
    {
        //判断需要添加button组件的物体是否有继承自MaskableGraphic的组件,有的话就勾选RaycastTarget
        if (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 Mask

    public static void OptimizingMask(Mask mask)
    {
        //判断需要添加mask组件的物体是否有继承自MaskableGraphic的组件,有的话就勾选RaycastTarget
        if (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

如果需要修改,可以把TMPpackage包从PackageManager中挪出来,改为本地Package

相关推荐
HookJames4 小时前
解决Claude帐号被封,利用VSCode+OpenRouter搭建本地环境
ide·vscode·编辑器
ManchiBB4 小时前
OpenClaw 移动端部署
编辑器
linux修理工4 小时前
VSCODE 使用LMSTUDIO本地显卡amd588 开发app
ide·vscode·编辑器
谢斯4 小时前
[vscode] vscode右键修复
ide·vscode·编辑器
小圣贤君5 小时前
从「选中一段」到「整章润色」:编辑器里的 AI 润色是怎么做出来的
人工智能·electron·编辑器·vue3·ai写作·deepseek·写小说
应用市场5 小时前
无人机动态推力分配与倾斜纠正原理详解
游戏引擎·无人机·cocos2d
GJ_WL6 小时前
word自带公式编辑器自动将公式变成正体
编辑器·word
weiyvyy6 小时前
无人机嵌入式开发实战-安全机制与应急处理
人工智能·嵌入式硬件·安全·机器人·游戏引擎·无人机·信息化
真的是小恐龙吗?6 小时前
在VSCode中写latex文档,输入部分字符,如何自动补全自定义指令
ide·vscode·编辑器