在项目开发过程中我们必不可少的会将美术给的资源打包成图集来降低drawcall,减少包内存。
为了方便的生成图集,以及生成图片路径配置来方便通过图片名称快速定位所在的图集以及图片位置。
// 获取图片资源root下的所有文件夹
string[] allPath = Directory.GetDirectories(SpriteRootPath);
// 筛选出是sprite图片
string[] guids = AssetDatabase.FindAssets("t:Sprite",new []{allPath[i]});
// guid 转成资源路径
string spritePath = AssetDatabase.GUIDToAssetPath(guids[j]);
// 加载sprite资源
Sprite sp = AssetDatabase.LoadAssetAtPath(spritePath);
创建图集
// 创建图集
SpriteAtlas atlas = new SpriteAtlas();
// 添加图集所有图片
atlas.Add(sprite);
// 创建图集资源
AssetDatabase.CreateAsset(atlas,path);
由于项目使用的是lua热更新所已导出的SpriteConfig是lua脚本,导出文件的难度也不大,废话不多说,直接看下面完整代码吧
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEditor.U2D;
using UnityEngine;
using UnityEngine.U2D;
namespace Editor.UI.Atlas
{
public static class SpriteAtlasUtils
{
public class SpriteData
{
public string name;
public string path;
public string atlasName;
public Sprite sprite;
}
private const string SpriteRootPath = "Assets/UI/Sprite/";
private const string SpriteAtlasRootPath = "Assets/UI/Atlas";
private const string SpriteConfigPath = "Assets/Scripts/Lua/Configs/SpriteConfig.lua";
private const string
SpriteConfigTemplate = "Assets/Scripts/CS/Core/UI/LuaTemplate/SpriteConfigTemplate.txt"; // 模板文件
[MenuItem("My菜单/导出图集")]
private static void Execute()
{
float total = 5;
float temp = 0;
ShowProgress("检查是否重名", ++temp, total);
if (CheckTheSameName())
{
EditorUtility.ClearProgressBar();
return;
}
ShowProgress("生成图集数据", ++temp, total);
Dictionary> spriteDic = GenerateSpriteData();
ShowProgress("生成图集", ++temp, total);
GenerateSpriteAtlas(spriteDic);
ShowProgress("生成配置数据", ++temp, total);
GenerateSpriteConfig(spriteDic);
ShowProgress("生成图集结束", ++temp, total);
EditorUtility.DisplayDialog("导出图集", $"图集导出成功,总共导出 {spriteDic.Count} 张图集", "OK");
EditorUtility.ClearProgressBar();
}
[MenuItem("My菜单/清空图集")]
private static void Clear()
{
var guids = AssetDatabase.FindAssets("", new[] {SpriteAtlasRootPath});
for (int i = 0; i < guids.Length; i++)
{
AssetDatabase.DeleteAsset(AssetDatabase.GUIDToAssetPath(guids[i]));
}
AssetDatabase.Refresh();
}
// 生成图集数据
private static Dictionary> GenerateSpriteData()
{
// 获取图片资源root下的所有文件夹
string[] allPath = Directory.GetDirectories(SpriteRootPath);
Dictionary> atlasDic = new Dictionary>();
for (int i = 0; i < allPath.Length; i++)
{
string atlasName = Path.GetFileNameWithoutExtension(allPath[i]);
// 筛选出是sprite图片
string[] guids = AssetDatabase.FindAssets("t:Sprite",new []{allPath[i]});
List spriteDatas = new List();
for (int j = 0; j < guids.Length; j++)
{
// guid 转成资源路径
string spritePath = AssetDatabase.GUIDToAssetPath(guids[j]);
// 加载sprite资源
Sprite sp = AssetDatabase.LoadAssetAtPath(spritePath);
SpriteData data = new SpriteData();
data.name = Path.GetFileNameWithoutExtension(spritePath);
data.path = spritePath;
data.sprite = sp;
data.atlasName = atlasName;
spriteDatas.Add(data);
}
atlasDic.Add(atlasName,spriteDatas);
}
return atlasDic;
}
// 生成图集
private static void GenerateSpriteAtlas(Dictionary> spriteDic)
{
foreach (var datas in spriteDic)
{
// 创建图集
SpriteAtlas atlas = new SpriteAtlas();
// 添加图集所有图片
atlas.Add(datas.Value.Select(t=> t.sprite).ToArray());
string path = SpriteAtlasRootPath + "/" + datas.Key + ".spriteatlas";
if (!Directory.Exists(SpriteAtlasRootPath))
{
Directory.CreateDirectory(SpriteAtlasRootPath);
}
// 创建图集资源
AssetDatabase.CreateAsset(atlas,path);
}
// 刷新文件
AssetDatabase.Refresh();
}
// 检查是否重名
private static bool CheckTheSameName()
{
Dictionary> pathDic = new Dictionary>();
List theSameKeys = new List();
// 获取所有图片文件夹
string[] allPath = Directory.GetDirectories(SpriteRootPath);
for (int i = 0; i < allPath.Length; i++)
{
// 获取文件夹下的所有资源唯一标识id
string[] guids = AssetDatabase.FindAssets("t:Sprite",new []{allPath[i]});
for (int j = 0; j < guids.Length; j++)
{
// 通过资源guid获得资源路径
string spritePath = AssetDatabase.GUIDToAssetPath(guids[j]);
string spName = Path.GetFileNameWithoutExtension(spritePath);
List pathList = null;
if (pathDic.TryGetValue(spName,out pathList))
{
if (!theSameKeys.Contains(spName))
{
theSameKeys.Add(spName);
}
}
else
{
pathList = new List();
pathDic.Add(spName,pathList);
}
pathList.Add(spritePath);
}
}
if (theSameKeys.Count > 0)
{
string msg = "";
for (int i = 0; i < theSameKeys.Count; i++)
{
List pList = pathDic[theSameKeys[i]];
for (int j = 0; j < pList.Count; j++)
{
msg = msg + pList[j] + "\n";
}
}
if (EditorUtility.DisplayDialog("出现同名sprite", msg, "确定"))
{
}
return true;
}
return false;
}
// 生成配置
private static void GenerateSpriteConfig(Dictionary> spriteDic)
{
StreamReader streamReader = File.OpenText(SpriteConfigTemplate);
string template = streamReader.ReadToEnd();
streamReader.Close();
StreamWriter streamWriter = File.CreateText(SpriteConfigPath);
StringBuilder atlasPathStr = new StringBuilder();
StringBuilder spritePathStr = new StringBuilder();
StringBuilder spriteAtlasPathStr = new StringBuilder();
foreach (var info in spriteDic)
{
string atlasName = info.Key;
string atlasPath = SpriteAtlasRootPath + atlasName;
atlasPathStr.AppendLine(string.Format("\t{0} = '{1}';", atlasName,atlasPath));
for (int i = 0; i < info.Value.Count; i++)
{
spritePathStr.AppendLine(string.Format("\t['{0}'] = '{1}';",info.Value[i].name ,info.Value[i].path));
spriteAtlasPathStr.AppendLine(string.Format("\t['{0}'] = {1};",info.Value[i].name,"M.AtlasPath." + atlasName));
}
}
template = template.Replace("$ATLASPATH$", atlasPathStr.ToString())
.Replace("$SPRITEPATH$", spritePathStr.ToString())
.Replace("$SPRITEATLASPATH$", spriteAtlasPathStr.ToString());
streamWriter.WriteLine(template);
streamWriter.Close();
}
// 显示进度
private static void ShowProgress(string info,float tmp,float total)
{
EditorUtility.DisplayProgressBar("生成图集", info, tmp / total);
}
}
}