Unity 编辑器-创建模板脚本,并自动绑定属性,添加点击事件

当使用框架开发时,Prefab挂载的很多脚本都有固定的格式。从Unity的基础模板创建cs文件,再修改到应有的模板,会浪费一些时间。尤其是有大量的不同界面时,每个都改一遍,浪费时间不说,还有可能遗漏或错改。写个脚本创建指定的模板代替C#基础模板。

注:当前脚本使用的NGUI,使用UGUI时替换对应的Component即可

代码

using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;

public class MediatorScriptCreator
{
    
    
    private const string MenuItemText1 = "Assets/Create/模板脚本/创建Mediator模板脚本";
    private const string MenuItemText3 = "Assets/Create/模板脚本/添加Mediator模板脚本";
    [MenuItem(MenuItemText1, false, 25)]
    public static void CreateScript()
    {
    
    
        CreateScript(false);
    }
   
    
    [MenuItem(MenuItemText3, false, 25)]
    public static void AddScript()
    {
    
    
        AddComp();
    }
    
    private static List<GameObject> _nodeList;
    private static List<UISprite> _imgList;
    private static List<UIButton> _btnList;
    private static List<UILabel> _labelList;
    private static List<UISlider> _sliderList;

    private static void CreateScript(bool isPartial)
    {
    
    

        var assetPath = AssetDatabase.GetAssetPath(Selection.activeObject);
        var directoryPath = System.IO.Path.GetDirectoryName(assetPath);
        var folderName = System.IO.Path.GetFileName(directoryPath);
        var folderPath = $"Assets/Game/GameLogic/{
      
      folderName}";
        if (!Directory.Exists(folderPath))
        {
    
    
            if (directoryPath != null) Directory.CreateDirectory(folderPath);
        }

        var scriptPath = $"{
      
      folderPath}/{
      
      Selection.activeObject.name}Mediator.cs";
        if (File.Exists(scriptPath))
        {
    
    
            Debug.LogError($"The script \"{
      
      scriptPath}\" already exists.");
            return;
        }

        var myPrefab = AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
        // 获取 Prefab 的所有子对象
        GetNodeData(myPrefab);

        var txt = $@"using UnityEngine;
namespace PD
{
     
     {
    public {
      
      (isPartial ? "partial" : "")} class {
      
      Selection.activeObject.name}Mediator : NGuiFormMasterLogic
    {
     
     {
        public override string FacadeName
        {
     
     {
            get {
     
     { return HomeFacade.Name; }}//TODO:修改FacadeName
        }}

        public new const string NAME = {
      
      $"\"{ 
         Selection.activeObject.name}Mediator\""};

        public override void OnConstruct(object userData)
        {
     
     {
            base.OnConstruct(userData);
            MediatorName = NAME;
        }}
";
        var txtEnd = $@"
    }}
}}";
        for (var i = 0; i < _nodeList.Count; i++)
        {
    
    
            var name = _nodeList[i].name[2..];
            name = name[..1].ToUpper() + name[1..];
            var str = $@"
        [SerializeField] private GameObject {
      
      name};
";
            txt += str;
        }

        for (var i = 0; i < _imgList.Count; i++)
        {
    
    
            var name = _imgList[i].name[2..];
            name = name[..1].ToUpper() + name[1..];
            var str = $@"
        [SerializeField] private UISprite {
      
      name};
";
            txt += str;
        }

        for (var i = 0; i < _labelList.Count; i++)
        {
    
    
            var name = _labelList[i].name[2..];
            name = name[..1].ToUpper() + name[1..];
            var str = $@"
        [SerializeField] private UILabel {
      
      name};
";
            txt += str;
        }

        for (var i = 0; i < _btnList.Count; i++)
        {
    
    
            var name = _btnList[i].name[2..];
            name = name[..1].ToUpper() + name[1..];
            var str = $@"
        [SerializeField] private UIButton {
      
      name};
";
            txt += str;
        }

        for (var i = 0; i < _sliderList.Count; i++)
        {
    
    
            var name = _sliderList[i].name[2..];
            name = name[..1].ToUpper() + name[1..];
            var str = $@"
        [SerializeField] private UISlider {
      
      name};
";
            txt += str;
        }

        for (var i = 0; i < _btnList.Count; i++)
        {
    
    
            var name = _btnList[i].name[2..];
            name = name[..1].ToUpper() + name[1..];
            var str = $@"


        public void On{
      
      name}Click()
        {
     
     {
           
        }}

";
            txt += str;
        }


        txt += txtEnd;
        EditorPrefs.SetString("creatorPath", assetPath);
        EditorPrefs.SetString("creatorName", myPrefab.name);
        EditorPrefs.SetString("creatorScriptPath", scriptPath);
        File.WriteAllText(scriptPath, txt);
        AssetDatabase.Refresh();
    }

    public static void AddComp()
    {
    
    
        var scriptName = EditorPrefs.GetString("creatorName");
        string[] guids = AssetDatabase.FindAssets(scriptName);

        if (guids.Length > 0)
        {
    
    
            var assetPath = EditorPrefs.GetString("creatorPath");
            string path = AssetDatabase.GUIDToAssetPath(guids[0]);
            MonoScript monoScript = AssetDatabase.LoadAssetAtPath<MonoScript>(path);
            System.Type type = monoScript.GetClass();
            var prefab =
                GameObject.Instantiate(
                    AssetDatabase
                        .LoadMainAssetAtPath(
                            assetPath)) as GameObject; // PrefabUtility.LoadPrefabContents(assetPath);//
            var component = prefab.AddComponent(type);
            // 获取所有字段
            var fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
            var list = prefab.GetComponentsInChildren<Transform>(true).Where(a => a.name.StartsWith("m_")).ToList();

            foreach (FieldInfo field in fields)
            {
    
    
                // 判断字段是否被序列化
                var attributes = field.GetCustomAttributes(typeof(SerializeField), false);
                if (attributes.Length > 0)
                {
    
    
                    var temp = field.Name + "";
                    var name = temp[..1].ToLower() + temp[1..];
                    var go = list.FirstOrDefault(a => a.name == $"m_{
      
      name}");
                    if (go != null)
                    {
    
    
                        list.Remove(go);
                        var btn = go.GetComponent<UIButton>();
                        var slider = go.GetComponent<UISlider>();
                        var img = go.GetComponent<UISprite>();
                        var txt = go.GetComponent<UILabel>();
                        if (btn != null)
                        {
    
    
                            var str = $"On{
      
      field.Name}Click";
                            Debug.Log(str);
                            var delegateFunc1 = new EventDelegate(component as MonoBehaviour, str);
                            btn.onClick.Add(delegateFunc1);
                            field.SetValue(component, btn);
                        }
                        else if (slider != null)
                        {
    
    
                            field.SetValue(component, slider);
                        }
                        else if (img != null)
                        {
    
    
                            field.SetValue(component, img);
                        }
                        else if (txt != null)
                        {
    
    
                            field.SetValue(component, txt);
                        }
                        else
                        {
    
    
                            field.SetValue(component, go.gameObject);
                        }
                    }
                }
            }

            // GetNodeData(prefab);
            // PrefabUtility.SaveAsPrefabAssetAndConnect(prefab, assetPath);
            PrefabUtility.SaveAsPrefabAssetAndConnect(prefab, assetPath, InteractionMode.AutomatedAction);
            Object.DestroyImmediate(prefab);
            AssetDatabase.Refresh();
        }
        else
        {
    
    
            Debug.LogError($"请先生成脚本");
        }
    }
    [MenuItem(MenuItemText1, true)]
    public static bool CreatorNormal()
    {
    
    
        if (!Selection.activeObject) return false;
        var prefabAssetType = PrefabUtility.GetPrefabAssetType(Selection.activeObject);
        return prefabAssetType != PrefabAssetType.NotAPrefab;

    }
    
    [MenuItem(MenuItemText3, true)]
    public static bool AddScript1()
    {
    
    
        if (!Selection.activeObject) return false;
        var prefabAssetType = PrefabUtility.GetPrefabAssetType(Selection.activeObject);
        return prefabAssetType != PrefabAssetType.NotAPrefab;

    }
    private static void GetNodeData(GameObject prefab)
    {
    
    
        Transform[] nodes = prefab.GetComponentsInChildren<Transform>(true);
        _nodeList = new List<GameObject>();
        _imgList = new List<UISprite>();
        _labelList = new List<UILabel>();
        _btnList = new List<UIButton>();
        _sliderList = new List<UISlider>();                                                                                              
        // 遍历所有子对象
        foreach (var node in nodes)
        {
    
    
            if (!node.gameObject.name.StartsWith("m_")) continue;
            var btn = node.GetComponent<UIButton>();
            var img = node.GetComponent<UISprite>();
            var label = node.GetComponent<UILabel>();
            var slider = node.GetComponent<UISlider>();
            if (btn != null)
            {
    
    
                _btnList.Add(btn);
            }
            else if (slider != null)
            {
    
    
                _sliderList.Add(slider);
            }
            else if (img != null)
            {
    
    
                _imgList.Add(img);
            }
            else if (label != null)
            {
    
    
                _labelList.Add(label);
            }
            else
            {
    
    
                _nodeList.Add(node.gameObject);
            }
        }
    }
}



使用方法

知识点

1.字符串使用@前缀,可以不使用\n换行。和$搭配使用时,字符串中如果有 { 需要用 { { 两个大括号表示,第一个为转义。 字符串中有 ” 时,需要使用反斜杠 " 转义
2.判断物体是不是Prefab,PrefabUtility.GetPrefabAssetType(Selection.activeObject) != PrefabAssetType.NotAPrefab;
3.[MenuItem(MenuItemText2, true)] 第二个参数 bool值表示是否显示本扩展方法
4.获取指定脚本所有的Pulbic[SerializeField]的属性: type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)

猜你喜欢

转载自blog.csdn.net/hzhnzmyz/article/details/131054256