【备忘】Unity中处理libgdx图集(根据atlas文件分割图片)

最近接手新项目,要本地化上渠道,所以需要reskin图片资源。但发现图集文件是未曾接触过的文件,经一番网上搜寻,发现是libgdx打包的。

参考文章:

Unity批处理生成/拆分图集_TopGames的博客-CSDN博客_unity图集拆分
libGDX游戏开发之文理打包(八)_凌康ACG的博客-CSDN博客_libgdx开发的游戏

(软件:gdx-texture-packer-gui

地址:https://github.com/crashinvaders/gdx-texture-packer-gui/

不想编译的话,直接下载release最新版)
言归正传,首先用gdx-texture-packer-gui(我下载的版本是4.10.2,不同版本可能略有差异)

将原项目的图集用自带的切图功能(Texture unpacker),分割成小图,然后增删修改对应文件,再合成一张大图集


打开.atlas文件看看内容:

dialog.png
size: 1993, 664
format: RGBA8888
filter: Nearest, Nearest
repeat: none
1_star
  rotate: false
  xy: 1754, 99
  size: 111, 103
  orig: 111, 103
  offset: 0, 0
  index: -1
2_star
  rotate: false
  xy: 1658, 425
  size: 112, 110
  orig: 112, 110
  offset: 0, 0
  index: -1

从中可看出,1-5行是整图大概信息,而后面是散图的具体信息;

所以大概思路就是读取atlas文件内的数据,根据具体散图的数据修改已有整图的分割数据(TextureImporter,SpriteMetaData)

具体代码参考:Unity批处理生成/拆分图集_TopGames的博客-CSDN博客_unity图集拆分
我这里做了部分修改:

 

同级目录下,放入同名atlas文件,选中图片,右键ModifyByAltas,即可完成切图信息修改。

using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Text;

public class ModifyByAltas
{
    /// <summary>
    /// 子图 信息
    /// </summary>
    internal class GDXAtlasElement
    {
        internal string name;
        internal Rect rect;
    }
    /// <summary>
    /// 图集 信息
    /// </summary>
    internal class GDXAtlas
    {
        internal string name;
        internal List<GDXAtlasElement> elements;
    }
    /// <summary>
    /// 解析图集配置表工具类
    /// </summary>
    internal class GDXAtlasUtility
    {
        internal static bool ParseAtlas(string atlasTxtFile, out GDXAtlas atlas)
        {
            atlas = null;
            if (!File.Exists(atlasTxtFile))
            {
                Debug.Log($"Doesnt exist atlasTxtFile:{atlasTxtFile}");
                return false;
            }
            var lines = new List<string>();
            foreach (var line in File.ReadLines(atlasTxtFile,Encoding.UTF8))
            {
                if (string.IsNullOrWhiteSpace(line))
                {
                    continue;
                }
                lines.Add(line);
            }
            if (lines.Count <= 0)
            {
                Debug.Log($"lines.Count <= 0 lines:{lines.Count}");
                return false;
            }
            string atlasName = lines[0].Trim();
            List<GDXAtlasElement> elements = new List<GDXAtlasElement>();
            for (int i = 5; i < lines.Count;)
            {
                if (i + 6 > lines.Count)
                {
                    break;
                }

                string eName = lines[i];
                Debug.Log($"eName:{eName} idx:{i}");
                string[] eXyValues = lines[i + 2].Trim().Split(':')[1].Trim().Split(',');
                string[] eSizeValues = lines[i + 3].Trim().Split(':')[1].Trim().Split(',');

                GDXAtlasElement spElement = new GDXAtlasElement();
                spElement.name = eName.Trim();

                Vector2 position = new Vector2(float.Parse(eXyValues[0].Trim()), float.Parse(eXyValues[1].Trim()));
                Vector2 size = new Vector2(float.Parse(eSizeValues[0].Trim()), float.Parse(eSizeValues[1].Trim()));
                spElement.rect = new Rect(position, size);
                elements.Add(spElement);
                i += 7;
            }
            atlas = new GDXAtlas();
            atlas.name = atlasName;
            atlas.elements = elements;
            return true;
        }
    }

    [MenuItem("Assets/ModifyByAltas")]
    static private void AutoSliceAtlas()
    {
        EditorUtility.DisplayCancelableProgressBar("Progress", "Slice Atlas...", 0);
        string selectObjDir = GetDirPath(AssetDatabase.GetAssetPath(Selection.activeInstanceID));
        
        string[] dirs = { selectObjDir }; 
        var assetIds = AssetDatabase.FindAssets("t:Texture", dirs);
        for (int i = 0; i < assetIds.Length; i++)
        {
            string spFileName = AssetDatabase.GUIDToAssetPath(assetIds[i]);
            var spTex = AssetDatabase.LoadAssetAtPath<Texture>(spFileName);

            string atlasTxtFile = string.Format("{0}{1}{2}", Application.dataPath.Substring(0, Application.dataPath.Length - 6), spFileName.Substring(0, spFileName.Length - 4),".atlas");
            Debug.Log($"atlasTxtFile:{atlasTxtFile} spFileName:{spFileName}");
            if (!GDXAtlasUtility.ParseAtlas(atlasTxtFile, out GDXAtlas gdxAtlas))
            {
                Debug.Log("false");
                continue;
            }
            SpriteMetaData[] spSheet = new SpriteMetaData[gdxAtlas.elements.Count];
            for (int elemIndex = 0; elemIndex < gdxAtlas.elements.Count; elemIndex++)
            {
                var eDt = gdxAtlas.elements[elemIndex];
                var spDt = new SpriteMetaData();
                var fixRect = eDt.rect;
                //libgdx图集坐标系原点是左上角, 这里需要转换到Unity坐标系(左下角)
                fixRect.y = spTex.height - fixRect.y - fixRect.size.y;
                spDt.name = eDt.name;
                spDt.rect = fixRect;
                spDt.pivot = Vector2.one * 0.5f;
                spDt.border = Vector4.zero;
                spDt.alignment = (int)SpriteAlignment.Custom;

                spSheet[elemIndex] = spDt;
            }
            var texImporter = AssetImporter.GetAtPath(spFileName) as TextureImporter;
            texImporter.spritesheet = spSheet;
            texImporter.spriteImportMode = SpriteImportMode.Multiple;
            texImporter.isReadable = true;
            Undo.RecordObject(texImporter, "Test Undo");
            texImporter.SaveAndReimport();
            EditorUtility.DisplayCancelableProgressBar("Progress", "Slice Atlas...", (i + 1) / (float)assetIds.Length);
            
            

        }
        EditorUtility.ClearProgressBar();
    }

    
    public static string GetDirPath(string tpath)
    {
        if (string.IsNullOrEmpty(tpath)) return "";
        int tidx = tpath.LastIndexOf('/');
        string path = tpath.Substring(0, tidx);
        return path;
    }
}

猜你喜欢

转载自blog.csdn.net/hrlr1230/article/details/127518049