SpriteAtlas
SpriteAtlas 是Unity2017新增得UGUI圖集工具,與之前版本的圖集工具SpritePacker對比,參考上一篇文章:
https://blog.csdn.net/u014794120/article/details/100126439
上篇文章提供了兩種圖集打包方式的優缺點,以及UGUI在使用過程中DrawCall問題的優化,本篇主要提供SpriteAtlas打包批處理工具的分享。
AtlasAutoPacker
AtlasAutoPacker,提供了四個基礎圖集打包的規則:
- 根據路徑配置,自動批處理打包
- 選中路徑下所有Sprite資源打包(包含子文件夾),逐個添加方式
- 選中路徑下所有Sprite資源打包(不包含子文件夾),逐個添加方式
- 完全打包一個Folder,添加整個Folder
支持圖集壓縮格式Format、Compressor Quality、默認設置
支持SpriteAtlas ImportSetiing選項設置,Include In Build、AllowRotation,Tight Packing,Pading、ReadWrite Enable……
Code
代碼如下:
using System.IO;
using UnityEditor;
using UnityEditor.U2D;
using UnityEngine;
using UnityEngine.U2D;
using System.Collections.Generic;
public class AtlasAutoPacker : Editor
{
/// <summary>
/// 打包圖集類型
/// </summary>
public enum PackType
{
DeepAssets = 0, //指定路徑下所有Sprite資源,包含子文件夾
Assets = 1, //指定路徑下所有Sprite資源,不包含子文件夾
Folder = 2, //打包一個Folder
}
private static string _atlasPath = "Assets/Resources/GameAssets/Logic/UISpriteAtlases/";
private static string _extention = ".spriteatlas";
private static string _texturePath = "Assets/Resources/GameAssets/UI/New Resources/dabao/";
/// <summary>
/// 生成圖集操作基礎路徑
/// 這些路徑下的所有子文件夾,除白名單外,一個Fold生成一個圖集
/// </summary>
private static List<string> _texturePathes = new List<string>() {
"Assets/Resources/GameAssets/UI/XXX/",
};
/// <summary>
/// 每個基礎路徑下,個別文件夾不能自動打包圖集
/// 這些路徑下資源不自動打包圖集(都是大圖、或者小圖大圖未分類、或者文件夾下有細分的AB規則、只有一張圖打了反而浪費)
/// 需要手動處理打包
/// </summary>
private static Dictionary<string, List<string>> whiteDic = new Dictionary<string, List<string>>()
{
{"Assets/Resources/GameAssets/UI/New Resources/dabao/" ,new List<string>(){
"aaaaaa",
"bbbbbb",
} },
{"Assets/Resources/GameAssets/UI/New Resources/gongyong/" ,new List<string>(){
"cccccc",
"dddddd",
} }
};
[MenuItem("Assets/AtlasPacker/AutoPack")]
public static void AutoSetAtlasContents()
{
foreach (var path in _texturePathes)
PackPath(path);
}
[MenuItem("Assets/AtlasPacker/Pack This Folder")]
public static void PackThisFolder()
{
string selectionpath = string.Empty;
foreach (Object obj in Selection.GetFiltered(typeof(Object), SelectionMode.Assets))
{
selectionpath = AssetDatabase.GetAssetPath(obj);
if (File.Exists(selectionpath))
{
selectionpath = Path.GetDirectoryName(selectionpath);
}
break;
}
PackOneFolder(selectionpath, PackType.Folder);
}
[MenuItem("Assets/AtlasPacker/Pack Folder`s Children")]
public static void PackThisFolderChildren()
{
string selectionpath = string.Empty;
foreach (Object obj in Selection.GetFiltered(typeof(Object), SelectionMode.Assets))
{
selectionpath = AssetDatabase.GetAssetPath(obj);
if (File.Exists(selectionpath))
{
selectionpath = Path.GetDirectoryName(selectionpath);
}
break;
}
PackOneFolder(selectionpath, PackType.Assets);
}
[MenuItem("Assets/AtlasPacker/Pack All In Folder")]
public static void PackAllInThisFolde()
{
string selectionpath = string.Empty;
foreach (Object obj in Selection.GetFiltered(typeof(Object), SelectionMode.Assets))
{
selectionpath = AssetDatabase.GetAssetPath(obj);
if (File.Exists(selectionpath))
{
selectionpath = Path.GetDirectoryName(selectionpath);
}
break;
}
PackOneFolder(selectionpath, PackType.DeepAssets);
}
/// <summary>
/// resPath 下的每個文件夾資源打成一個圖集
/// </summary>
/// <param name="resPath"></param>
private static void PackPath(string resPath)
{
DirectoryInfo srcDir = new DirectoryInfo(resPath);
if (srcDir != null && srcDir.Exists)
{
List<string> whiteList = whiteDic.ContainsKey(resPath) ? whiteDic[resPath] : new List<string>();
DirectoryInfo[] dirs = srcDir.GetDirectories();
foreach (var oneDir in dirs)
{
if (whiteList.Contains(oneDir.Name))
{
Debug.LogWarning("PackPath Ignore folder " + oneDir.Name);
continue;
}
string dirPath = FullPath2Relative(oneDir.FullName);
PackOneFolder(dirPath, PackType.Folder);
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
else
{
Debug.LogError("Auto Packer Atlas Failed! texture not exit :" + resPath);
}
}
static void PackOneFolder(string folderPath, PackType packType)
{
List<Object> assets = FilterAssets(folderPath, packType);
if (assets.Count > 0)
{
string atlasPath = AtlasPath(folderPath);
SpriteAtlas atlas = GenerateAtlas();
atlas.Add(assets.ToArray());
if (AssetDatabase.DeleteAsset(atlasPath))
Debug.Log(string.Format("Deleta Old Atlas: {0}", atlasPath));
AssetDatabase.CreateAsset(atlas, atlasPath);
//設置atlas AssetBundleName 爲atlasName
//AssetImporter importer = AssetImporter.GetAtPath(atlasPath);
//importer.assetBundleName = Path.GetFileNameWithoutExtension(atlasPath);
//importer.SaveAndReimport();
Debug.Log(string.Format("Packing Path: {0} into one Atlas: {1} ", folderPath, atlasPath));
}
}
static List<Object> FilterAssets(string folderPath, PackType packType)
{
List<Object> objects = new List<Object>();
DefaultAsset folderAsset = AssetDatabase.LoadAssetAtPath(folderPath, typeof(DefaultAsset)) as DefaultAsset;
switch (packType)
{
case PackType.DeepAssets:
string[] assetsGUIDs = AssetDatabase.FindAssets("t:texture", new string[] { folderPath });
foreach (var guid in assetsGUIDs)
{
Sprite sp = AssetDatabase.LoadAssetAtPath<Sprite>(AssetDatabase.GUIDToAssetPath(guid)) as Sprite;
if (sp != null)
objects.Add(sp);
}
break;
case PackType.Assets:
if(Directory.Exists(folderPath))
{
DirectoryInfo dir = new DirectoryInfo(folderPath);
FileInfo[] files = dir.GetFiles("*", SearchOption.TopDirectoryOnly);
foreach(var fi in files)
{
string spritePath = FullPath2Relative(fi.FullName);
Sprite sp = AssetDatabase.LoadAssetAtPath<Sprite>(spritePath);
if (sp != null)
objects.Add(sp);
}
}
break;
case PackType.Folder:
if (folderAsset != null)
objects.Add(folderAsset);
break;
default:
if (folderAsset != null)
objects.Add(folderAsset);
break;
}
return objects;
}
static string FullPath2Relative(string fullPath)
{
string relativePath = fullPath.Substring(fullPath.IndexOf("Assets"));
relativePath = relativePath.Replace("\\", "/");
return relativePath;
}
static string AtlasPath(string resFolderPath)
{
string atlasName = resFolderPath.Substring(resFolderPath.IndexOf("New Resources"));
atlasName = atlasName.Replace("/","_");
return resFolderPath + "/" + atlasName + _extention;
}
private static SpriteAtlas GenerateAtlas()
{
// 設置參數 可根據項目具體情況進行設置
SpriteAtlasPackingSettings packSetting = new SpriteAtlasPackingSettings()
{
blockOffset = 1,
enableRotation = false,
enableTightPacking = false,
padding = 2,
};
SpriteAtlasTextureSettings textureSetting = new SpriteAtlasTextureSettings()
{
readable = false,
generateMipMaps = false,
sRGB = true,
filterMode = FilterMode.Bilinear,
};
SpriteAtlas atlas = new SpriteAtlas();
atlas.SetPackingSettings(packSetting);
atlas.SetTextureSettings(textureSetting);
ApplyTexturePlatFormCompressSettingDefault(atlas);
atlas.SetIncludeInBuild(true);
atlas.SetIsVariant(false);
return atlas;
}
private static void ApplyTexturePlatFormCompressSettingDefault(SpriteAtlas atlas)
{
TextureImporterPlatformSettings textureCompressDefault = new TextureImporterPlatformSettings();
textureCompressDefault.overridden = false;
textureCompressDefault.name = "DefaultTexturePlatform";
textureCompressDefault.textureCompression = TextureImporterCompression.Compressed;
textureCompressDefault.compressionQuality = (int)UnityEngine.TextureCompressionQuality.Best;
atlas.SetPlatformSettings(textureCompressDefault);
TextureImporterPlatformSettings textureCompressIOS = new TextureImporterPlatformSettings();
textureCompressIOS.name = "iPhone";
textureCompressIOS.overridden = true;
textureCompressIOS.textureCompression = TextureImporterCompression.Compressed;
textureCompressIOS.format = TextureImporterFormat.ASTC_RGBA_6x6;
textureCompressIOS.compressionQuality = (int)UnityEngine.TextureCompressionQuality.Best;
atlas.SetPlatformSettings(textureCompressIOS);
TextureImporterPlatformSettings textureCompressAndroid = new TextureImporterPlatformSettings();
textureCompressAndroid.name = "Android";
textureCompressAndroid.overridden = true;
textureCompressAndroid.textureCompression = TextureImporterCompression.Compressed;
textureCompressAndroid.format = TextureImporterFormat.ASTC_RGBA_6x6;
textureCompressAndroid.compressionQuality = (int)UnityEngine.TextureCompressionQuality.Best;
atlas.SetPlatformSettings(textureCompressAndroid);
}
}