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

相关推荐
世洋Blog3 小时前
SiYangUnityEventSystem,一个Unity中的事件系统
观察者模式·unity·c#·游戏引擎·事件系统
晚风予卿云月3 小时前
Linux编辑器—vim的使用
linux·编辑器·vim
呆呆敲代码的小Y3 小时前
【Unity实战篇】| 游戏滑动框添加特殊效果,如实时高亮显示、曲线滑动等
游戏·unity·游戏引擎·实战·u3d·免费游戏·unity实战技巧
DeadPool loves Star3 小时前
VSCode关闭Shell内联建议
ide·vscode·编辑器
超哥归来3 小时前
关闭vscode中git的行历史提示
ide·git·vscode·编辑器
Tatalaluola4 小时前
【Quest开发】用unity UI快速实现交互
unity·游戏引擎
UP_Continue4 小时前
Linux--vim编辑器
linux·编辑器·vim
技术小甜甜4 小时前
[Godot] 在 Godot 3.1 中配置 ADB 可执行文件的实用指南
游戏·adb·游戏引擎·godot
技术小甜甜4 小时前
【Godot】【入门】Godot 是什么?适合做哪些类型的游戏(附路线图+避坑清单)
游戏·游戏引擎·godot
码界奇点4 小时前
Unity WebGL输入支持终极指南解决浏览器输入难题的完整方案
unity·容器·游戏引擎·鸿蒙系统·webgl