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

相关推荐
小妖6661 小时前
vscode vue文件单行注释失效解决办法
ide·vscode·编辑器
火柴盒zhang2 小时前
websheet之 编辑器
开发语言·前端·javascript·编辑器·spreadsheet·websheet
Geek__19922 小时前
VSCode远程图形化GDB
ide·vscode·编辑器
星火撩猿3 小时前
常见游戏引擎介绍与对比
unity·ue5·游戏引擎·godot
sky_smile_Allen4 小时前
[Unity]-[UI]-[Prefab] 关于Unity UGUI 的布局及组件讲解
ui·unity·游戏引擎
xx155802862xx4 小时前
vscode 打开csv乱码
ide·vscode·编辑器
静听夜半雨5 小时前
CANoe入门——3、新建LIN工程及LIN DataBase(LDF文件)的创建
网络·数据库·c++·编辑器
信号处理学渣5 小时前
Git命令行中vim的操作
git·编辑器·vim
虾球xz6 小时前
游戏引擎学习第244天: 完成异步纹理下载
c++·学习·游戏引擎
太妃糖耶9 小时前
URP-利用矩阵在Shader中实现物体的平移和缩放
unity·矩阵