Unity技术之UGUI-SpriteAtlas(图集)查看工具

Unity技术之UGUI-SpriteAtlas(图集)查看工具

简介

Unity提供了UGUI用于UI系统的制作,与NGUI相比有一个很大的不同,UGUI弱化了Atlas(图集)的概念,通过添加了SpriteAtlas的概念可以自动将指定的Sprite合并为一个图集。有时候需要查看图集打包后的具体的情况,Unity提供了对应的预览功能,但是其中也存在着一些问题:Sprite的数量过多,造成超出指定的SpriteAtlas的尺寸的话,对于旧的版本中(比如Unity2017),将会把超出的部分直接忽略掉,而且没有任何的错误信息,在后续的版本中(比如Unity2018.3)中Unty修复了此问题,会生成多张图集,只是在预览窗口中无法预览到。

本文将介绍一种方式,可以查看SpriteAtlas打包后得到的所有的图集,以方便在开发中对图集进行调整。

注意事项:如果您使用的是Unity旧的版本,比如Unity2017,本文中的部分内容您将无法使用,因为部分接口是在2018后面的版本中添加的。

声明

本文中的内容属于个人总结整理而来,个人水平有限,对于部分细节难免有理解错误及遗漏之处,如果您在阅读过程中有所发现,希望您能指正,同时文章中的部分内容也参考了其它大神的文章,如果文章中的内容侵犯了您的权益,表示非常歉意,请您指出,我将尽快修改。

如果您进行转载,请标明出处。

Unity技术之UGUI-SpriteAtlas(图集)查看工具(http://www.liyubin.com/articles/2019/08/02/1564714684778.html)

Unity中的SpriteAtlas

通过在project中的右键菜单可以创建SpriteAtlas,方式为Create->Sprite Atlas,可以在指定的位置创建SpriteAtlas

Unity技术之UGUI-SpriteAtlas(图集)查看工具_第1张图片

本来此处不再详细介绍SpriteAtlas的使用及各个参数的含义,其它的文章会详细的介绍。

在Objects for Packing中可以添加单个的Sprite,也可以添加Sprite所在的整个目录

Objects for packing

点击Pack Preview按钮后可以预览打包后的图集,如果打包的图集超出指定的图片的尺寸是无法显示的。

如何查看SpriteAtlas生成的所有的图集

默认情况下,Unity并未提供对应的方式,所以基本上从正常的方式上解决此问题已经不可能了。所以只能靠其它方式来处理了,于是就有了下面的解决方法。

主体思想是:

1. 通过代码调用Pack Preview按钮,实现SpriteAtlas打包
2. 通过反射调用Unity隐藏的函数及方法
3. 将反射得到的图片输出到指定的磁盘上

工具的使用方式:

1. 选中需要导出图集的SpriteAtlas资源
2. 将下述的脚本添加到项目的Editor的目录中
3. 直接拷贝添加的话,会有异常提示,下文有对应的说明,请查看一下,解决完异常后进行下一步
4. 点击菜单中的Game/UI/Atlas/SpriteAtlas Exporter、
5. 选择想要存储导出的图集的位置
6. 导出完成,如果您按下文说明中的修复了异常,在Windows平台上会自动打开存储的文件夹
using DotEditor.Core.Util;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using UnityEditor;
using UnityEditor.U2D;
using UnityEngine;
using UnityEngine.U2D;
using SystemObject = System.Object;

namespace DotEditor.Core.UI.Atlas
{
    public static class SpriteAtlasExporter
    {
        public static string[] Export(SpriteAtlas atlas,string dirPath)
        {
            string platformName = "Standalone";
            if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.Android)
            {
                platformName = "Android";
            }
            else if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.iOS)
            {
                platformName = "iPhone";
            }

            TextureImporterPlatformSettings tips = atlas.GetPlatformSettings(platformName);
            TextureImporterPlatformSettings cachedTips = new TextureImporterPlatformSettings();
            tips.CopyTo(cachedTips);

            tips.overridden = true;
            tips.format = TextureImporterFormat.RGBA32;
            atlas.SetPlatformSettings(tips);

            List<string> texturePathList = new List<string>();

            SpriteAtlasUtility.PackAtlases(new SpriteAtlas[] { atlas}, EditorUserBuildSettings.activeBuildTarget);
            MethodInfo getPreviewTextureMI = typeof(SpriteAtlasExtensions).GetMethod("GetPreviewTextures", BindingFlags.Static | BindingFlags.NonPublic);
            Texture2D[] atlasTextures = (Texture2D[])getPreviewTextureMI.Invoke(null, new SystemObject[] { atlas });
            if (atlasTextures != null && atlasTextures.Length > 0)
            {
                for (int i = 0; i < atlasTextures.Length; i++)
                {
                    Texture2D packTexture = atlasTextures[i];
                    byte[] rawBytes = packTexture.GetRawTextureData();

                    Texture2D nTexture = new Texture2D(packTexture.width, packTexture.height, packTexture.format, false, false);
                    nTexture.LoadRawTextureData(rawBytes);
                    nTexture.Apply();
                    string textPath = string.Format("{0}/{1}_{2}.png", dirPath, atlas.name, i);
                    File.WriteAllBytes(textPath, nTexture.EncodeToPNG());

                    texturePathList.Add(textPath);
                }
            }

            atlas.SetPlatformSettings(cachedTips);

            return texturePathList.ToArray();
        }


        [MenuItem("Game/UI/Atlas/SpriteAtlas Exporter")]
        private static void ExportAltas()
        {
            List<SpriteAtlas> atlasList = new List<SpriteAtlas>();
            if(Selection.objects!=null && Selection.objects.Length>0)
            {
                foreach(var obj in Selection.objects)
                {
                    if(obj.GetType() == typeof(SpriteAtlas))
                    {
                        atlasList.Add(obj as SpriteAtlas);
                    }
                }
            }

            if(atlasList.Count==0)
            {
                EditorUtility.DisplayDialog("Tips", "Please Selected SpriteAtlas", "OK");
                return;
            }

            string dirPath = EditorUtility.OpenFolderPanel("Save Dir", "D:/", "");
            if(string.IsNullOrEmpty(dirPath))
            {
                EditorUtility.DisplayDialog("Tips", "Please Selected a folder","OK");
                return;
            }

            foreach(var atlas in atlasList)
            {
                Export(atlas, dirPath);
            }

            ExplorerUtil.OpenExplorerFolder(dirPath);
        }
    }
}

注意:上述代码中使用到了ExplorerUtil.OpenExplorerFolder(dirPath);,其目的是在Windows平台上直接打开导出的图片的目录,可以参与另一篇文章:Unity技术 资源管理器explorer使用,如果您不需要的话,上述代码删除,并把包名删除即可

参考资料

  • UnityCsReference

你可能感兴趣的:(Unity,UGUI,C#,Tools)