【备忘】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;
    }
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity获取多个外部文件图片可以通过以下步骤实现: 1. 创建一个空的GameObject作为图片的容器。 2. 创建一个脚本来加载外部文件图片。在脚本,使用Unity的AssetBundle功能来加载外部文件图片资源。 3. 在脚本使用AssetBundle.LoadFromFile方法加载外部文件,该方法将返回一个AssetBundle对象。 4. 使用AssetBundle对象的LoadAllAssets方法加载所有的图片资源,该方法将返回一个Object数组。 5. 遍历Object数组,使用类型转换将Object转换为Texture2D或Sprite对象,然后将其添加到GameObject。 以下是示例代码: ```csharp using UnityEngine; public class LoadImagesFromExternalFiles : MonoBehaviour { public string[] filePaths; // 外部文件的路径数组 void Start() { GameObject imageContainer = new GameObject("ImageContainer"); foreach (string filePath in filePaths) { AssetBundle assetBundle = AssetBundle.LoadFromFile(filePath); Object[] assets = assetBundle.LoadAllAssets(); foreach (Object asset in assets) { if (asset is Texture2D) { Texture2D texture = (Texture2D)asset; // 创建一个新的Sprite对象 Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.zero); // 创建一个新的GameObject来显示图片 GameObject imageObject = new GameObject("Image"); // 添加SpriteRenderer组件,并将Sprite对象设置为其Sprite属性 imageObject.AddComponent<SpriteRenderer>().sprite = sprite; // 将图片对象添加到容器 imageObject.transform.SetParent(imageContainer.transform); } } assetBundle.Unload(false); // 卸载AssetBundle资源 } } } ``` 以上代码将会加载每个外部文件的所有图片资源,并将其显示在Unity场景的一个空GameObject上。 这样就可以通过加载外部文件图片资源来实现在Unity获取多个外部文件图片

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值