SRPG游戏开发(十四)第五章 颜色映射与职业动画 - 六 颜色组编辑器(EditorWindow)

本文介绍了在Unity中开发SRPG游戏时,如何创建一个颜色组编辑器EditorWindow,用于自动填充贴图颜色和方便地编辑颜色组。详细讲解了自动填充贴图颜色的方法、读取Texture2D颜色时遇到的问题及其原因,以及颜色组编辑器的实现过程,包括颜色对比和ScrollView滚动条的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


返回目录

第五章 颜色映射与职业动画


六        颜色组编辑器(EditorWindow)


每次导入进素材还要把颜色一个一个的输入进去,是不是很麻烦?这一节我们来解决这个问题,更方便的编辑我们的颜色组。


1        自动填充贴图颜色(ColorChartEditor.cs)


首先,创建ColorChartEditor.cs


using UnityEditor;
using UnityEngine;

namespace DR.Book.SRPG_Dev.ColorPalette
{
    [CanEditMultipleObjects]
    [CustomEditor(typeof(ColorChart))]
    public class ColorChartEditor : Editor
    {
        public ColorChart chart
        {
            get { return target as ColorChart; }
        }

        public override void OnInspectorGUI()
        {
            DrawDefaultInspector();

            // TODO 自动填充贴图颜色
        }
    }
}

同样的,我们并不需要自定义Inspector面板,而只是需要一个自动获取贴图颜色的方法。


其次,要获取贴图的颜色,首先得先获取贴图。我们用一个按钮,来获取贴图并获取颜色:


            if (GUILayout.Button("Load Colors From Texture"))
            {
                string path = EditorUtility.OpenFilePanelWithFilters("Create Chart", "Assets", new string[] { "PNG Image", "png", "JPG Image", "jpg", "GIF Image", "gif" });
                if (!string.IsNullOrEmpty(path) && path.Contains(Application.dataPath))
                {
                    path = path.Replace(Application.dataPath, "Assets");
                    Texture2D texture = AssetDatabase.LoadAssetAtPath<Texture2D>(path);
                    // TODO 获取贴图颜色
                }
            }

最后,我们在ColorChart.cs中完成获取贴图颜色的方法,Texture需要设置成可读:


        /// <summary>
        /// 从Texture中读取颜色
        /// </summary>
        /// <param name="chart"></param>
        /// <param name="texture"></param>
        /// <returns></returns>
        public static bool LoadColorsFromTexture(ColorChart chart, Texture2D texture)
        {
            if (chart == null || texture == null)
            {
                return false;
            }

            Color[] colors = texture.GetPixels();
            List<Color> list = new List<Color>();
            for (int i = 0; i < colors.Length; i++)
            {
                if (colors[i].a != 0 && !list.Contains(colors[i]))
                {
                    list.Add(colors[i]);
                }
            }
            chart.m_Colors = list.ToArray();
            return true;
        }

调用此方法来填充颜色:


            if (GUILayout.Button("Load Colors From Texture"))
            {
                string path = EditorUtility.OpenFilePanelWithFilters("Create Chart", "Assets", new string[] { "PNG Image", "png", "JPG Image", "jpg", "GIF Image", "gif" });
                if (!string.IsNullOrEmpty(path) && path.Contains(Application.dataPath))
                {
                    path = path.Replace(Application.dataPath, "Assets");
                    Texture2D texture = AssetDatabase.LoadAssetAtPath<Texture2D>(path);
                    ColorChart.LoadColorsFromTexture(chart, texture);
                }
            }

是不是简单多了?只要Texture可读,选择此选项立刻填充颜色。


2        动态读取Texture2D颜色的坑


读取Texture2D的方法有很多,可以使用ResourcesAssetBundleWWWSystem.IO等方法读取,在Editor中还可以用AssetDatabase读取。但这其中有一个问题。


在用WWWSystem.IO读取一部分PNG(我只测试了PNG)的Texture2D时,颜色可能会严重失真,获取的颜色和实际颜色相差非常大,测试了一下,和原始颜色RGB255)数值都有相差1020不等。而其他方式读取的没有问题。


出现这个的原因,经过测试,是PNG文件的问题,PNG文件也分多种。本人用Photoshop测试结果:

  • 另存为PNG,没有问题,容量较大;
  • 快速导出,层导出与导出PNG,颜色失真,容量较小;
  • 使用旧版导出PNG,颜色失真,容量较小。

可以看出,另存为时保存了一些额外信息,这些信息和颜色有关(你用PS打开这些PNG时,你可以看到,普通PNG是“RGB颜色”模式,而那些较小的文件是“索引颜色”模式,所以额外容量至少有RGB颜色信息)。


5 - 12 PNGPS中的模式


所以如果你使用WWWSystem.IO读取文件后,如果要放到ColorChart中,要注意文件是否正确。


你可能会问Unity其它方式读取它为什么没有问题,这是因为Unity在内部帮我们保存了文件的一些额外信息,例如.meta文件就是一个例子。


由于我对图像学不是很了解,只能尽量不使用WWWSystem.IO直接读取Texture2D,而实际项目中也基本很难遇到,多数都是用AssetBundle。发现这个坑的原因是,WWWSystem.IO读取的文件无论Unity中设置如何,都可以读写(毕竟是流),所以使用它们读取了文件,结果就中坑了,不过也因此学到了一些东西。


3        颜色组编辑器(ColorChartEditorWindow.cs)


我们要在一个窗口中编辑颜色组的颜色,所以新建Editor窗口类ColorChartEditorWindow.cs


using UnityEditor;
using UnityEngine;

namespace DR.Book.SRPG_Dev.ColorPalette
{
    public class ColorChartEditorWindow : EditorWindow
    {
        [MenuItem("Window/SRPG/Color Chart")]
        public static ColorChartEditorWindow OpenColorChartEditorWindow()
        {
            ColorChartEditorWindow window = EditorWindow.GetWindow<ColorChartEditorWindow>(false, "Color Chart");
            window.Show();
            return window;
        }
    }
}

在窗口中,我们需要对比源颜色和转换颜色,来更好的辅助我们编辑颜色。所以他还需要两个ColorChart;而且因为颜色数量可能很多,需要ScrollView滚动条来控制;绘制Window是在OnGUI()Callback里面,添加它们。


        private ColorChart m_SrcChart;
        private ColorChart m_SwapChart;

        private Vector2 m_Scroll = Vector2.zero;

        public ColorChart src
        {
            get { return m_SrcChart; }
            set { m_SrcChart = value; }
        }

        public ColorChart swap
        {
            get { return m_SwapChart; }
            set { m_SwapChart = value; }
        }

        private void OnGUI()
        {
            // TODO 绘制GUI
        }

首先,要绘制GUI,首先我们需要两个ColorChart,必须保证它们都同时存在:


            // 设置src与swap
            src = EditorGUILayout.ObjectField("Source Chart", src, typeof(ColorChart), false) as ColorChart;
            swap = EditorGUILayout.ObjectField("Swap Chart", swap, typeof(ColorChart), false) as ColorChart;
            if (src == null || swap == null)
            {
                EditorGUILayout.HelpBox("Please select source chart and swap chart.", MessageType.Info);
                return;
            }

其次,要能设置它们的颜色数量,且Swap Chart的颜色数量要和Source Chart的颜色数量相等:


            // 设置Color的数量
            EditorGUI.BeginChangeCheck();
            int count = Mathf.Max(0, EditorGUILayout.DelayedIntField("Color Count", src.count));
            if (EditorGUI.EndChangeCheck() && src.count != count)
            {
                src.count = count;
                EditorUtility.SetDirty(src);
            }

            if (swap.count != src.count)
            {
                int swapCount = swap.count;
                swap.count = src.count;
                if (swapCount < src.count)
                {
                    ColorChart.CopyColors(src, swapCount, swap, swapCount, src.count - swapCount);
                }
                EditorUtility.SetDirty(swap);
            }

在这之中,如果Swap Chart的颜色数量小于Source Chart的颜色数量的话,是需要保留原来的颜色,并且新增颜色和Source Chart对应颜色相同,这样更便于我们编辑,打开ColorChart.cs添加方法CopyColors


        /// <summary>
        /// 复制颜色
        /// </summary>
        /// <param name="src"></param>
        /// <param name="srcIndex"></param>
        /// <param name="dst"></param>
        /// <param name="dstIndex"></param>
        /// <param name="length"></param>
        public static void CopyColors(ColorChart src, int srcIndex, ColorChart dst, int dstIndex, int length)
        {
            Array.Copy(src.m_Colors, srcIndex, dst.m_Colors, dstIndex, length);
        }

最后,来绘制我们的颜色:


            // 设置颜色
            EditorGUI.BeginChangeCheck();
            m_Scroll = EditorGUILayout.BeginScrollView(m_Scroll, "box");
            {
                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField("Index", GUILayout.MaxWidth(50));
                EditorGUILayout.LabelField("Source Chart", GUILayout.MaxWidth(150));
                EditorGUILayout.LabelField("Swap Chart", GUILayout.MaxWidth(150));
                EditorGUILayout.EndHorizontal();
                for (int i = 0; i < count; i++)
                {
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.LabelField(i.ToString(), GUILayout.MaxWidth(50));
                    src[i] = EditorGUILayout.ColorField(src[i], GUILayout.MaxWidth(150));
                    swap[i] = EditorGUILayout.ColorField(swap[i], GUILayout.MaxWidth(150));
                    EditorGUILayout.EndHorizontal();
                }
            }
            EditorGUILayout.EndScrollView();
            if (EditorGUI.EndChangeCheck())
            {
                EditorUtility.SetDirty(src);
                EditorUtility.SetDirty(swap);
            }

这样我们就完成了编辑器。将Source Chart放入,然后想编辑哪个Swap Chart就把哪个拖入到Swap Chart中,就可以对比看了,来看看效果吧。


5 - 13 Color Chart Editor Window

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值