Unity编辑器扩展:基于ScriptableWizard批量为预设添加继承于MonoBehaviour的脚本

为了实现,批量为一些特定的prefab或者子对象添加统一的脚本,实现过程中发现,在继承自ScriptableWizard的类中,定义一个MonoBehaviour类型的变量,我们并不能把继承自他的子类拖过去。如图:

	[Tooltip("添加的脚本内容")]
    [Header("添加的脚本")]
    public MonoBehaviour addMono;

窗口中虽然正确识别类型,但是我们不能很方便的把脚本拖过来:
在这里插入图片描述
在定义的时候,改用

	public MonoScript addMono;

在为对象添加的时候,需要用到 GetClass() 方法类获取添加脚本的Type。

完整代码如下(支持拖放目录或者预设):

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;

public class ModelAddComWizard : ScriptableWizard
{
    [Tooltip("目录直接拖过来会自动识别完整路径")]
    [Header("目录-->设置目录(推荐)或路径")]
    public UnityEngine.Object floder;
    [Tooltip("自动识别目录路径")]
    public string autoGeneratePath = "";
    [Tooltip("检测预设名称是否包含此字符串")]
    [Header("目标对象名称【包含】")]
    public string targetName;
    [Tooltip("检测预设名称不能包含此字符串")]
    [Header("目标对象名称【不包含】")]
    public string targetNoName = null;
    [Tooltip("添加的脚本内容")]
    [Header("添加的脚本")]
    public MonoScript addMono;

    private int changeNum;

    [MenuItem("Pioneer/批量为预设添加Script")]
    public static void CreateWizard()
    {
        ScriptableWizard.DisplayWizard<ModelAddComWizard>("组件添加", "GO!");
    }

    void OnWizardCreate()
    {
        CheckFloder();
    }

    void CheckFloder()
    {
        if(floder != null)
            autoGeneratePath = AssetDatabase.GetAssetPath(floder.GetInstanceID());
        if(string.IsNullOrEmpty(autoGeneratePath))
            throw new ArgumentException("错误的目录!");
        //检测是目录还是预设
        if (autoGeneratePath.IndexOf(".prefab") != -1)
        {
            GameObject go = AssetDatabase.LoadAssetAtPath(autoGeneratePath, typeof(GameObject)) as GameObject;
            if (go != null)
            {
                CheckGameobject(go, autoGeneratePath);
                AssetDatabase.SaveAssets();
                EditorUtility.DisplayDialog("提示", "预设\n【" + go.name + "】\n检测完毕!!", "朕已阅");
            }
        }
        else
        {
            CheckByPath(autoGeneratePath);
        }
    }

    void CheckByPath(string path)
    {
        changeNum = 0;
        List<string> prefabPaths = GetAllPrefabsPath(path);
        for (int i = 0; i < prefabPaths.Count; i++)
        {
            GameObject obj = AssetDatabase.LoadAssetAtPath(prefabPaths[i], typeof(UnityEngine.Object)) as GameObject;
            CheckGameobject(obj, prefabPaths[i]);
        }
        AssetDatabase.SaveAssets();
        EditorUtility.DisplayDialog("提示", "目录【" + path + "】\n"+ changeNum + "个!", "朕已阅");
    }

    List<string> GetAllPrefabsPath(string directory)
    {
        if (string.IsNullOrEmpty(directory))
            throw new ArgumentException("错误的路径!");
        List<string> assetPaths = new List<string>();
        string[] guids2 = AssetDatabase.FindAssets("t:Prefab", new string[] { directory });
        for (int i = 0; i < guids2.Length; i++)
        {
            assetPaths.Add(AssetDatabase.GUIDToAssetPath(guids2[i]));
        }
        return assetPaths;
    }

    void CheckGameobject(GameObject go, string path)
    {
        if (go == null) return;
        if (go.name.IndexOf("Root") == -1) return;
        for(int i = 0;i<go.transform.childCount;i++)
        {
            Transform child = go.transform.GetChild(i);
            if(child.name.IndexOf(targetName) != -1)
            {
                if(!string.IsNullOrEmpty(targetNoName))
                {
                    if(child.name.IndexOf(targetNoName) == -1)
                    {
                        Type ty = addMono.GetClass();
                        var com = child.GetComponent(ty);
                        if (com == null)
                        {
                            var add = child.gameObject.AddComponent(ty);
                            if (add != null)
                                EditorUtility.SetDirty(go);
                            changeNum++;
                        }
                    }
                }
            }
        }
    }
}

你可能感兴趣的:(unity,C#,unity)