使用平台说明:Win7 , Unity2017 , TexturePacker 4.9
起因是项目优化时,为了将UGUI原始的SpritePacker替换,我们打包AB时发现始终会包含原始的Texture(图集中元素)文件,这样就产生了大量冗余。TexturePacker提供了许多方便的命令行指令,具体参数可以通过命令行窗口TexturePacker.exe查看。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 |
/// <summary> /// 基于Texture Packer的批量图集打包 /// </summary> public class BatchAtlasPackerEditor { private static string PACKER_ARGS = " --data \"{0}.tpsheet\" --format unity-texture2d --sheet \"{0}.png\"" + " --max-size 2048 --disable-rotation --no-trim --opt RGBA8888 --texture-format png " + "--scale 1 {1}";// private static string MULTIP_PACKER_ARGS = " --data \"{0}-{{n}}.tpsheet\" --format unity-texture2d --sheet \"{0}_{{n}}.png\" " + "--multipack --max-size 2048 --disable-rotation --no-trim --opt RGBA8888 --texture-format png " + "--scale 1 {1}";// //查询原来的Sprite 图集分包信息 private static Dictionary<string, TextureAtlas> findSpriteAtlas(string srcTextutresPath) { Dictionary<string, TextureAtlas> textureAtlas = new Dictionary<string, TextureAtlas>(); string[] textures = AssetDatabase.FindAssets("t:Texture2D", new[] { srcTextutresPath }); for (int i = 0, length = textures.Length; i < length; i++) { string texPath = AssetDatabase.GUIDToAssetPath(textures[i]); TextureImporter importer = AssetImporter.GetAtPath(texPath) as TextureImporter; string atlasName = importer.spritePackingTag; if (string.IsNullOrEmpty(atlasName)) { UnityEngine.Debug.LogWarning(texPath); continue; } TextureAtlas ta = null; if (!textureAtlas.TryGetValue(atlasName, out ta)) { ta = new TextureAtlas(atlasName); textureAtlas[atlasName] = ta; } ta.Textures.Add(texPath); } return textureAtlas; } private static void buildAtlas(TextureAtlas atlas , bool isMultiPack) { string atlasPath = "Assets/AtlasTextures/" + atlas.AtlasName; //存放的目录 StringBuilder buf = new StringBuilder(); List<string> texturePaths = atlas.Textures; for (int i = 0 , count = texturePaths.Count ; i < count; i++) { buf.AppendFormat("\"{0}\" ", texturePaths[i]); } string files = buf.ToString(); string args = string.Empty; if (isMultiPack) args = string.Format(MULTIP_PACKER_ARGS, Path.GetFullPath(atlasPath), files); else args = string.Format(PACKER_ARGS, Path.GetFullPath(atlasPath), files); startTexturePacker(args); } private static void startTexturePacker(string args) { ProcessStartInfo start = new ProcessStartInfo("TexturePacker.exe"); start.Arguments = args; start.CreateNoWindow = true; start.WindowStyle = ProcessWindowStyle.Hidden; start.ErrorDialog = false; start.UseShellExecute = false; start.RedirectStandardOutput = true; start.RedirectStandardError = true; start.RedirectStandardInput = true; start.StandardOutputEncoding = System.Text.UTF8Encoding.UTF8; start.StandardErrorEncoding = System.Text.UTF8Encoding.UTF8; Process p = Process.Start(start); UnityEngine.Debug.Log(p.StandardOutput.ReadToEnd()); string error = p.StandardError.ReadToEnd(); if (!string.IsNullOrEmpty(error) && error.Contains("load")) UnityEngine.Debug.LogError(error); p.WaitForExit(); p.Dispose(); } private static string getTextureFiles(string folder) { string[] textures = AssetDatabase.FindAssets("t:Texture2D", new[] { folder }); StringBuilder buf = new StringBuilder(); for (int i = 0; i < textures.Length; i++) { buf.AppendFormat("\"{0}\" ", AssetDatabase.GUIDToAssetPath(textures[i])); } return buf.ToString(); } //批量打包图集 public static void BatchAtlasPack() { //find atlas Dictionary<string, TextureAtlas> textureAtlas = findSpriteAtlas(); onBuildAtlas(textureAtlas); } private static void saveTextureImport(TextureImporter textureImport) { // textureImport.textureType = TextureImporterType.Default; // textureImport.mipmapEnabled = false; textureImport.filterMode = FilterMode.Bilinear; textureImport.maxTextureSize = 2048; textureImport.wrapMode = TextureWrapMode.Clamp; //compress TextureImporterPlatformSettings defaultSetting = textureImport.GetDefaultPlatformTextureSettings(); defaultSetting.textureCompression = TextureImporterCompression.Compressed; defaultSetting.compressionQuality = (int)TextureCompressionQuality.Best; TextureImporterPlatformSettings texPlatformSetting = textureImport.GetPlatformTextureSettings("Android"); texPlatformSetting.format = TextureImporterFormat.ETC2_RGBA8; texPlatformSetting.compressionQuality = (int)TextureCompressionQuality.Best; TextureImporterPlatformSettings iosSetting = textureImport.GetPlatformTextureSettings("iPhone"); iosSetting.format = TextureImporterFormat.PVRTC_RGBA4; iosSetting.compressionQuality = (int)TextureCompressionQuality.Best; textureImport.SaveAndReimport(); } private static string unescapeName(string name) { return name.Replace("%23", "#").Replace("%3A", ":").Replace("%3B", ";") .Replace("%25", "%").Replace("/", "-"); } //重新导入绑定九宫格数据 private static void setAtlasSpriteBorders(TextureAtlas atlas) { Dictionary<string, Vector4> spriteBorders = findAtlasSpriteBorders(atlas); //update sheet string sheetPath = string.Format("{0}/{1}/{1}.tpsheet", ATLAS_PARENT, atlas.AtlasName); if (!File.Exists(sheetPath)) return; string atlasName = Path.GetFileNameWithoutExtension(sheetPath); string[] lines = File.ReadAllLines(sheetPath); for (int i = 0; i < lines.Length; i++) { string line = lines[i]; if (line.StartsWith(":borders=")) { string a2 = line.Remove(0, 9).ToLower().Trim(); lines[i] = line.Replace(a2, "enabled"); break; } } for (int i = 0; i < lines.Length; i++) { string line = lines[i]; if (string.IsNullOrEmpty(line) || line.StartsWith("#") || line.StartsWith(":")) continue; string[] metaDatas = line.Split(';'); string spriteName = unescapeName(metaDatas[0]); int index = 1 + 4 + 2 - 1; //name + rect + pivot Vector4 border; if (spriteBorders.TryGetValue(spriteName, out border)) { if (metaDatas.Length < index + 4) { string[] newMetaDatas = new string[metaDatas.Length + 4]; Array.Copy(metaDatas, newMetaDatas, metaDatas.Length); metaDatas = newMetaDatas; } metaDatas[index + 1] = " " + (int)border.x; metaDatas[index + 2] = Convert.ToString((int)border.z); metaDatas[index + 3] = Convert.ToString((int)border.w); metaDatas[index + 4] = Convert.ToString((int)border.y); } lines[i] = string.Join(";", metaDatas); } File.WriteAllLines(sheetPath, lines); //reimporter atlas string atlasPath = string.Format("{0}/{1}/{1}.png", ATLAS_PARENT, atlasName); TextureImporter ti = AssetImporter.GetAtPath(atlasPath) as TextureImporter; if (ti == null) { UnityEngine.Debug.Log("Cant find atlas !" + atlasPath); return; } saveTextureImport(ti); } private static Dictionary<string, Vector4> findAtlasSpriteBorders(TextureAtlas atlas) { string[] textures = atlas.Textures.ToArray(); Dictionary<string, Vector4> spriteBorders = new Dictionary<string, Vector4>(); for (int i = 0; i < textures.Length; i++) { string assetPath = textures[i]; string spriteName = Path.GetFileNameWithoutExtension(assetPath); TextureImporter ti = AssetImporter.GetAtPath(assetPath) as TextureImporter; if (ti.spriteBorder != Vector4.zero) spriteBorders[spriteName] = ti.spriteBorder; } return spriteBorders; } } public class TextureAtlas { public string AtlasName; public bool IsMultiPack; public List<string> Textures; public TextureAtlas(string atlasName) { AtlasName = atlasName; Textures = new List<string>(); } } |