编辑器扩展

自定义类型的显示:

public class TestClass
{
    public int value;
    public string name = "";
}

public class TestEditor : EditorWindow
{
    public static TestEditor window = null;

    [MenuItem("Test/MyEditor &t")]
    public static void ShowWindow()
    {
        window = EditorWindow.GetWindow(typeof(TestEditor), false, "TestEditor") as TestEditor;
    }

    private List<TestClass> lst = new List<TestClass>();
    private bool showFoldout = true;
    private Vector2 scrollPosition = Vector2.zero;

    int count
    {
        get { return lst.Count; }
        set 
        { 
            if(value < lst.Count)
            {
                lst.RemoveRange(value, lst.Count - value);
            }
            else if(value > lst.Count)
            {
                for(int i = 0; i < value; ++i)
                {
                    lst.Add(new TestClass());
                }
            }
        }
    }

    void OnGUI()
    {
        GUILayout.BeginArea(new Rect(0, 0, Screen.width, Screen.height), "", "box");
        GUILayout.BeginVertical("box");
        scrollPosition = GUILayout.BeginScrollView(scrollPosition, "box");      // 创建自适应滚动条

        // 创建折叠标签
        showFoldout = EditorGUILayout.Foldout(showFoldout, "Array");
        if (showFoldout)
        {
            GUILayout.BeginHorizontal();
            GUILayout.Label("count", GUILayout.Width(50));
            count = System.Convert.ToInt32(GUILayout.TextField(count.ToString()));
            GUILayout.EndHorizontal();

            // 逐行显示数据
            for (int i = 0; i < count; ++i)
            {
                GUILayout.BeginHorizontal();

                GUILayout.Label("name", GUILayout.Width(50));
                lst[i].name = GUILayout.TextField(lst[i].name);

                GUILayout.Label("value", GUILayout.Width(50));
                lst[i].value = System.Convert.ToInt32(GUILayout.TextField(lst[i].value.ToString()));

                GUILayout.EndHorizontal();
            }
        }

        GUILayout.EndVertical();
        GUILayout.EndScrollView();
        GUILayout.EndArea();
    }

}

  上述代码在自定义编辑器中显示了自定义结构TestClass的列表,效果如下所示:

  有个小细节值得一提,TestClass.name一定要初始化为"",不然现实会报错。

添加Project界面自定义菜单:

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

[CreateAssetMenu(menuName="Test/CreateMyObject")]
public class MyObject : ScriptableObject
{
    // 中心点
    public Vector3 Center;

    // 受击点
    public List<Vector3> HitPos = new List<Vector3>();

    // 受击点朝向
    public List<Vector3> HitDir = new List<Vector3>();
}

获取Hierarchy中gameobject所关联的本地资源prefab:

  var prefabSource = PrefabUtility.GetPrefabParent(prefab);

自定义ScriptableObject:

    [CreateAssetMenu(menuName = "Test/Numbers")]
    public class DataNumbers : ScriptableObject
    {
        public List<int> Values = new List<int>();
    }

    // 加载
    var numberAsset = AssetDatabase.LoadAssetAtPath<DataNumbers>(filePath);
    for(int i = 0; i < numberAsset.Values.Count; ++i)
    {
        Debug.Log(numberAsset.Values[i]);
    }
    }

    // 保存
    numberAsset.Values.Add(1);
    numberAsset.Values.Add(2);
    numberAsset.Values.Add(3);
    EditorUtility.SetDirty(numberAsset);
    AssetDatabase.SaveAssets();

SceneView显示当前鼠标位置:

 

using UnityEngine;
using UnityEditor;

public class WildTerrainEditor : EditorWindow
{
    private void OnEnable()
    {
        SceneView.onSceneGUIDelegate -= OnSceneGUI;
        SceneView.onSceneGUIDelegate += OnSceneGUI;
    }

    private void OnDestroy()
    {
        SceneView.onSceneGUIDelegate -= OnSceneGUI;
    }

    private void OnSceneGUI(SceneView sceneView)
    {
        UpdateMousePosition();

        Handles.BeginGUI();
        GUI.color = Color.red;
        GUI.Label(new Rect(Event.current.mousePosition.x, Event.current.mousePosition.y - 20, 100, 20),
            SceneViewMousPos.ToString());
        Handles.EndGUI();
    }
    
    private void UpdateMousePosition()
    {
        Event e = Event.current;

        Ray r = Camera.current.ScreenPointToRay(new Vector3(e.mousePosition.x, -e.mousePosition.y + Camera.current.pixelHeight));
        Vector3 mousePos = r.origin;
        SceneViewMousPos = mousePos;
    }
}

统一调整渲染深度信息:

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

namespace James
{
    [ExecuteInEditMode]
    public class UniformRenderDepth : MonoBehaviour
    {
        private const int   Invalid = -10000;
        public string       SortingLayerName;                       // 空表示不设置
        public int          SortingOrder = Invalid;                 // -10000表示不设置
        public int          RenderQueue = Invalid;                  // -10000表示不设置

        private void Start()
        {
            Set();
        }

        [ContextMenu("Set")]
        public void Set()
        {
            Renderer[] renderers = GetComponentsInChildren<Renderer>(true);
            foreach (var r in renderers)
            {
                if (RenderQueue != Invalid)
                {
                    if (Application.isPlaying)
                    {
                        r.material.renderQueue = RenderQueue;
                    }
                    else
                    {
                        r.sharedMaterial.renderQueue = RenderQueue;
                    }
                }
                if (string.IsNullOrEmpty(SortingLayerName) == false)
                {
                    r.sortingLayerName = SortingLayerName;
                }
                if (SortingOrder != Invalid)
                {
                    r.sortingOrder = SortingOrder;
                }
            }
        }

        [ContextMenu("Get")]
        public void Get()
        {
            Renderer[] renderers = GetComponentsInChildren<Renderer>(true);
            foreach (var r in renderers)
            {
                if (Application.isPlaying)
                {
                    RenderQueue = r.material.renderQueue;
                }
                else
                {
                    RenderQueue = r.sharedMaterial.renderQueue;
                }
                SortingLayerName = r.sortingLayerName;
                SortingOrder = r.sortingOrder;
                break;
            }
        }
    }
}

 子节点自动排布脚本:

public class AutoSetGroup : MonoBehaviour
{
    public Vector2 size = Vector2.one;
    public Vector2Int num = Vector2Int.one;

    [ContextMenu("Set")]
    public void Execute()
    {
        float hHalfSize = size.x / (2 * num.x);
        float vHalfSize = size.y / (2 * num.y);

        Vector2 topLeftPos = new Vector2(- 0.5f * size.x + hHalfSize, 0.5f * size.y - vHalfSize);

        int total = num.x * num.y;
        for(int i = 0; i < total; ++i)
        {
            if(i >= transform.childCount) return;

            var tran = transform.GetChild(i);
            int xIdx = i % num.x;
            int yIdx = i / num.x;

            var pos = tran.localPosition;
            pos.x = topLeftPos.x + xIdx * hHalfSize * 2;
            pos.y = topLeftPos.y - yIdx * vHalfSize * 2;
            tran.localPosition = pos;
        }

    }
}

 统计shader变种数量

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

namespace AOE.Editor
{
    public class ShaderVariantInfo
    {
        public string name;
        public int num;
    }

    public class Statistic_ShaderVariants : EditorWindow
    {
        private static EditorWindow window;

        private static List<ShaderVariantInfo> lst = new List<ShaderVariantInfo>();
        private static int shaderNum = 0;
        private static int variantNum = 0;

        private Vector2 m_scrollPos = Vector2.zero;
        public static Texture2D m_texRight = null;
        public static Texture2D m_texWrong = null;
        public static Texture2D m_texPlay = null;

        private void OnEnable()
        {
            m_texPlay = EditorGUIUtility.FindTexture("forward@2x");
            m_texRight = EditorGUIUtility.FindTexture("FilterSelectedOnly");
            m_texWrong = EditorGUIUtility.FindTexture("d_P4_DeletedLocal");
        }

        private void OnDisable()
        {
            m_texRight = null;
            m_texWrong = null;
        }

        [MenuItem("Tools/ShaderVariants")]
        public static void Execute()
        {
            if (window == null)
                window = (Statistic_ShaderVariants)GetWindow(typeof(Statistic_ShaderVariants));
            window.minSize = new Vector2(300, 300);
            var tex = EditorGUIUtility.FindTexture("d_WelcomeScreen.AssetStoreLogo");
            window.titleContent = new GUIContent("Searcher", tex);
            window.Show();
        }

        private void OnGUI()
        {
            GUILayout.BeginVertical();

            if (GUILayout.Button(new GUIContent("Scan", m_texPlay), GUILayout.Height(30)))
            {
                Scan();
            }

            if (lst.Count > 0)
            {
                using (new GUILayout.HorizontalScope())
                {
                    GUILayout.Label($"Shader总数:{shaderNum}", GUILayout.Width(110), GUILayout.Height(30));
                    GUILayout.Label($"Shader变种数量:{variantNum}", GUILayout.Height(30));
                }

                using (new GUILayout.HorizontalScope())
                {
                    GUILayout.Label("变重数量", GUILayout.Width(110), GUILayout.Height(30));
                    GUILayout.Label("Shader路径(点击可选中)", GUILayout.Height(30));
                }

                using (new GUILayout.VerticalScope("box"))
                {
                    using (var scrollView = new GUILayout.ScrollViewScope(m_scrollPos))
                    {
                        m_scrollPos = scrollView.scrollPosition;

                        foreach (var info in lst)
                        {
                            using (new GUILayout.HorizontalScope())
                            {
                                GUILayout.Label(info.num.ToString(), GUILayout.Width(100), GUILayout.Height(30));
                                var tex = info.num <= 32 ? m_texRight : m_texWrong;
                                if (GUILayout.Button(new GUIContent(info.name, tex), "label", GUILayout.Height(30)))
                                {
                                    Selection.activeObject = AssetDatabase.LoadAssetAtPath<Shader>(info.name);
                                }
                            }
                        }
                    }
                }
            }

            GUILayout.EndVertical();
        }

        private void Scan()
        {
            lst.Clear();
            shaderNum = 0;
            variantNum = 0;

            Assembly asm = Assembly.GetAssembly(typeof(UnityEditor.SceneView));
            System.Type shaderUtil = asm.GetType("UnityEditor.ShaderUtil");
            MethodInfo method = shaderUtil.GetMethod("GetVariantCount", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
            var shaderList = AssetDatabase.FindAssets("t:Shader", null);
            shaderNum = shaderList.Length;

            EditorUtility.DisplayProgressBar("Shader统计文件", "正在写入统计文件中...", 0f);
            int idx = 0;
            foreach (var str in shaderList)
            {
                EditorUtility.DisplayProgressBar("Shader统计文件", "正在写入统计文件中...", idx / shaderList.Length);

                var path = AssetDatabase.GUIDToAssetPath(str);
                Shader shader = AssetDatabase.LoadAssetAtPath(path, typeof(Shader)) as Shader;

                var variantCount = method.Invoke(null, new System.Object[] { shader, true });

                int num = int.Parse(variantCount.ToString());
                lst.Add(new ShaderVariantInfo()
                {
                    name = path,
                    num = num
                });

                variantNum += num;
                ++idx;
            }

            EditorUtility.ClearProgressBar();

            lst.Sort((a, b) => b.num.CompareTo(a.num));
        }
    }
}

 

posted @ 2014-09-08 17:57  斯芬克斯  阅读(924)  评论(0编辑  收藏  举报