unity编辑器扩展高级用法

在PropertyDrawer中,您不能使用来自GUILayoutEditorGUILayout的自动布局API,而只能使用来自GUIEditorGUI的绝对Rect API始终传递相应的起始位置和维度。

你需要

  • 计算显示嵌套内容所需的总高度
  • 将此高度添加到public override float GetPropertyHeight,这将告诉检查员根据Rect保留以绘制您的财产
  • 将为sub-editor保留的相应Rect传递到editor中,并在给定位置和尺寸处绘制

=>您不能简单地使用默认编辑器来实现这一点,因为它在PropertyDrawers无法使用的auto-layout系统中运行。

cs 复制代码
#region UNITY_EDITOR
using System.Collections.Generic;
using System;
using UnityEditor;
using static UnityEditor.Progress;
using UnityEngine;
using Unity.VisualScripting;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Xml.Linq;
using System.IO;

public class UICollector : MonoBehaviour
{


    public string GenerateClassName;
    public OperateSetting OperateSetting;
    public List<ComponentInfo> components = new List<ComponentInfo>();
   
    public void GenerateMainClass()
    {
  //  F:\AAAAAAAAAAAG4\UnityProject\MyDoor\trunk\client_root\Assets\Scripts\Game\Runtime\Logic\Dialog\_AirShipBodayTab.cs
        string mainPath = $"{Application.dataPath}/Scripts/Game/Runtime/Logic/Dialog/{GenerateClassName}.cs";
        if (!File.Exists(mainPath))
        {
            File.Create(mainPath).Close();         
        }

        UnityEditor.AssetDatabase.Refresh();
        File.WriteAllText(mainPath,
            @"using UnityEngine;
using System;
using UnityEngine.UI;
public partial class _D_CLASSNAME : Dialog
{
    public override bool IsFullScreen() { return true;}
    public override bool NeedShowCoins(){   return false; }
    protected override void OnCreate()
    {
                       
    }
}
".Replace("_D_CLASSNAME", GenerateClassName)
        );
        UnityEditor.AssetDatabase.Refresh();
        GeneratePartClass();

    }


    private void GeneratePartClass()
    {

        string fielddata = "";
        string referdata = "";
        foreach (var item in components)
        {
            if (!string.IsNullOrEmpty(item.name)&& item.component!=null)
            {
                fielddata += $"private {item.component.GetType().Name} {item.name};\n";
                referdata += $"{item.name} = transform.Find(\"{ item.path }\").GetComponent<{item.component.GetType().Name}>();\n";
            }
        }

        

        string baseTemp = @"using System;
using UnityEngine;
using UnityEngine.UI;

public partial class _D_CLASSNAME : Dialog
{
    FILEDLIST
    protected override void InitRef()
    {
      REFERENCE
    }
}
";
        string info = "";
        info = baseTemp.Replace("FILEDLIST", fielddata);
        info = info.Replace("_D_CLASSNAME", GenerateClassName);
        info = info.Replace("REFERENCE", referdata);
        string aprtPath = $"{Application.dataPath}/Scripts/Game/Runtime/Logic/Dialog/Partial/{GenerateClassName}.cs";
        if (!File.Exists(aprtPath))
        {
            File.CreateText(aprtPath).Close();
            UnityEditor.AssetDatabase.Refresh();         
        }

        File.WriteAllText(aprtPath, info);
        UnityEditor.AssetDatabase.Refresh();
    }



}



[Serializable]
public class ComponentInfo
{
    public string name;
    public string path;
    public int index;
    public UnityEngine.Component component;
    public GameObject go;
    public GameObject lastObject;
}
[CustomPropertyDrawer(typeof(ComponentInfo))]
public class ComponentInfoEditor : PropertyDrawer
{

    private UnityEngine.Object lastObject;
    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        return base.GetPropertyHeight(property, label) + 40;//这个总区域的高度
    }
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        GUI.color = Color.white;
        float span = 220;
        float width = 180;
        var f1Rect = new Rect(position.x + span * 1, position.y, width, 20);
        var f2Rect = new Rect(position.x + span * 0, position.y, width, 20);
        var f3Rect = new Rect(position.x, position.y + 20, width, 20);
        var f4Rect = new Rect(position.x + span * 1, position.y + 20, width, 20);
        var f5Rect = new Rect(position.x + span * 2, position.y + 20, width, 20);

        EditorGUIUtility.labelWidth = 70;

        var go = property.FindPropertyRelative("go").objectReferenceValue;
        if (go != null)
        {
            EditorGUI.PropertyField(f2Rect, property.FindPropertyRelative("go"));
            bool isChange = false;
           var lastObject = property.FindPropertyRelative("lastObject").objectReferenceValue;
            if (isChange == false) isChange = lastObject != go;
            property.FindPropertyRelative("lastObject").objectReferenceValue = go;
            UnityEngine.Component[] components = go.GetComponents<UnityEngine.Component>();
            List<string> types = new List<string>();
            foreach (UnityEngine.Component comp in components)
            {
                types.Add(comp.GetType().Name);
            }
            int nowindex = EditorGUI.Popup(f1Rect, property.FindPropertyRelative("index").intValue, types.ToArray());
            if (isChange == false) isChange = property.FindPropertyRelative("index").intValue != nowindex;
            property.FindPropertyRelative("index").intValue = nowindex;
            int index = property.FindPropertyRelative("index").intValue;
            property.FindPropertyRelative("component").objectReferenceValue = components[index];
            if (isChange || string.IsNullOrEmpty(property.FindPropertyRelative("name").stringValue))
            {
                string name = "m_" + components[index].GetType().Name.Substring(0, 4) + "_" + components[index].name;
                property.FindPropertyRelative("name").stringValue = name;
            }

            EditorGUI.PropertyField(f3Rect, property.FindPropertyRelative("name"));
            EditorGUI.PropertyField(f4Rect, property.FindPropertyRelative("component"));


            //当前挂载位置
            var parent = property.serializedObject.targetObject.GetComponent<Transform>();
            var curgo = go.GetComponent<Transform>();
            types.Clear();
            while (curgo != parent && curgo != null)
            {
                types.Add(curgo.name);
                curgo = curgo.parent;
            }
            string path = "";
            for (int i = types.Count - 1; i >= 0; i--)
            {
                path += (types[i] + (i != 0 ? "/" : ""));
            }
            property.FindPropertyRelative("path").stringValue = path;
            EditorGUI.PropertyField(f5Rect, property.FindPropertyRelative("path"));
 
        }
        else
        {
            EditorGUI.PropertyField(f2Rect, property.FindPropertyRelative("go"));
        }
    }
}


[Serializable]
public class OperateSetting
{
}

[CustomPropertyDrawer(typeof(OperateSetting))]
public class OperateSettingAEditor : PropertyDrawer
{
    private Dictionary<string, ComponentInfo> keyValuePairs = new Dictionary<string, ComponentInfo>();
    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        return base.GetPropertyHeight(property, label) + addHeight;
    }
    private float addHeight;
    private string repeatname;
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        //UnityEditor.EditorGUILayout.Space(60);
        var uiCollector = property.serializedObject.targetObject.GetComponent<UICollector>();
        if (string.IsNullOrEmpty(uiCollector.GenerateClassName))
        {
            uiCollector.GenerateClassName = $"_D_{uiCollector.transform.name.Replace("_d_", "")}";
        }

        if (GUI.Button(new Rect(position.x, position.y, position.width, 30), "生成CSharp"))
        {
            uiCollector.GenerateMainClass();
        }

        if (uiCollector.components.Count > 0)
        {
            keyValuePairs.Clear();
            bool isRepeat = false;
            foreach (var item in uiCollector.components)
            {
                if (!keyValuePairs.ContainsKey(item.name))
                {
                    keyValuePairs.Add(item.name,item);
                }
                else
                {
                    //GUI.color = Color.red; // 设置错误文本颜色为红色
                    repeatname = item.name;
                    isRepeat = true;
                    break;
                }
            }
            if (isRepeat)
            {
                GUI.Label(new Rect(position.x, position.y + 30, position.width, 40), "重复提示:" + repeatname + "字段重复", new GUIStyle());
                addHeight = 40;
            }
            else
            {
                addHeight = 30;
            }
        }
    }
}



#endregion
相关推荐
Sitarrrr2 小时前
【Unity】ScriptableObject的应用和3D物体跟随鼠标移动:鼠标放置物体在场景中
3d·unity
极梦网络无忧2 小时前
Unity中IK动画与布偶死亡动画切换的实现
unity·游戏引擎·lucene
电子云与长程纠缠3 小时前
UE5.3中通过编辑器工具创建大纲菜单文件夹
java·ue5·编辑器
lucky九年3 小时前
vscode翻译插件
ide·vscode·编辑器
真·Wild·攻城狮4 小时前
【码农日常】Vscode Clangd初始化失败(Win10)
ide·vscode·编辑器
七灵微4 小时前
【测试】【Debug】vscode中同一个测试用例出现重复
ide·vscode·编辑器
逐·風10 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
_oP_i11 小时前
Unity Addressables 系统处理 WebGL 打包本地资源的一种高效方式
unity·游戏引擎·webgl
代码盗圣15 小时前
GODOT 4 不用scons编译cpp扩展的方法
游戏引擎·godot
4U24720 小时前
Linux入门之vim
linux·编辑器·vim·命令模式·底行模式