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

相关推荐
gameckisme9 分钟前
Selfloss,官方中文,解压即玩,
游戏·unity·游戏程序·图形渲染·cocos2d·贴图·游戏策划
Clank的游戏栈12 分钟前
Unity3D 自定义Debug双击溯源问题详解
unity
猿儿本无心1 小时前
vscode+vue3+vite项目配置stylelint 2024版本
ide·vscode·编辑器
以史为镜1 小时前
VSCode 创建Python 项目(最简单,最少步骤,无痛从pycharm迁移项目)
ide·vscode·编辑器
DC10202 小时前
Visual Studio Code 月刊 (2024-08)
ide·vscode·编辑器
结衣结衣.14 小时前
Linux环境下使用Git把代码上传到云端
linux·运维·服务器·c语言·git·elasticsearch·编辑器
tealcwu17 小时前
【Unity踩坑】为什么有Rigidbody的物体运行时位置会变化
unity·游戏引擎
EdSheeran乀18 小时前
虚幻中的c++(持续更新)
开发语言·c++·ue5·游戏引擎·ue4·虚幻
sjsjs1119 小时前
【Unity Shader】反射
unity·游戏引擎
叶浩成52019 小时前
wangeditor——cdn引入的形式创建一个简易版编辑器——js技能提升
开发语言·javascript·编辑器