public void OnGroupAtlases(BuildTarget target, UnityEditor.Sprites.PackerJob job, int[] textureImporterInstanceIDs) { List <Entry> entries = new List <Entry>(); foreach (int instanceID in textureImporterInstanceIDs) { TextureImporter ti = EditorUtility.InstanceIDToObject(instanceID) as TextureImporter; TextureFormat desiredFormat; ColorSpace colorSpace; int compressionQuality; ti.ReadTextureImportInstructions(target, out desiredFormat, out colorSpace, out compressionQuality); TextureImporterSettings tis = new TextureImporterSettings(); ti.ReadTextureSettings(tis); Sprite[] sprites = AssetDatabase.LoadAllAssetRepresentationsAtPath(ti.assetPath) .Select(x => x as Sprite) .Where(x => x != null) .ToArray(); foreach (Sprite sprite in sprites) { Entry entry = new Entry(); entry.sprite = sprite; entry.settings.format = desiredFormat; entry.settings.colorSpace = colorSpace; // Use Compression Quality for Grouping later only for Compressed Formats. Otherwise leave it Empty. entry.settings.compressionQuality = IsCompressedFormat(desiredFormat) ? compressionQuality : 0; entry.settings.filterMode = Enum.IsDefined(typeof(FilterMode), ti.filterMode) ? ti.filterMode : FilterMode.Bilinear; entry.settings.maxWidth = 2048; entry.settings.maxHeight = 2048; entry.settings.generateMipMaps = ti.mipmapEnabled; entry.settings.enableRotation = AllowRotationFlipping; if (ti.mipmapEnabled) { entry.settings.paddingPower = kDefaultPaddingPower; } else { entry.settings.paddingPower = (uint)EditorSettings.spritePackerPaddingPower; } #if ENABLE_ANDROID_ATLAS_ETC1_COMPRESSION entry.settings.allowsAlphaSplitting = ti.GetAllowsAlphaSplitting(); #endif //ENABLE_ANDROID_ATLAS_ETC1_COMPRESSION entry.atlasName = ParseAtlasName(ti.spritePackingTag); entry.packingMode = GetPackingMode(ti.spritePackingTag, tis.spriteMeshType); entry.anisoLevel = ti.anisoLevel; entries.Add(entry); } Resources.UnloadAsset(ti); } // First split sprites into groups based on atlas name var atlasGroups = from e in entries group e by e.atlasName; foreach (var atlasGroup in atlasGroups) { int page = 0; // Then split those groups into smaller groups based on texture settings var settingsGroups = from t in atlasGroup group t by t.settings; foreach (var settingsGroup in settingsGroups) { string atlasName = atlasGroup.Key; if (settingsGroups.Count() > 1) { atlasName += string.Format(" (Group {0})", page); } UnityEditor.Sprites.AtlasSettings settings = settingsGroup.Key; settings.anisoLevel = 1; // Use the highest aniso level from all entries in this atlas if (settings.generateMipMaps) { foreach (Entry entry in settingsGroup) { if (entry.anisoLevel > settings.anisoLevel) { settings.anisoLevel = entry.anisoLevel; } } } // 需要分离alpha通道的情况 if (TextureUtility.IsTransparent(settings.format)) { if (!CustomAtlasConfig.ShouldKeepAlpha(atlasName)) { if (CustomAtlasConfig.ShouldUseOutputAtlasTexture(atlasName)) { settings.format = TextureFormat.RGB24; } else { settings.format = TextureUtility.TransparentToNoTransparentFormat(settings.format); } } } job.AddAtlas(atlasName, settings); foreach (Entry entry in settingsGroup) { job.AssignToAtlas(atlasName, entry.sprite, entry.packingMode, SpritePackingRotation.None); } ++page; } } }
private static void WriteSpritesRenderData(List <AtlasEntry> atlasEntries) { if (atlasEntries == null) { return; } foreach (var atlasEntry in atlasEntries) { foreach (var spriteEntry in atlasEntry.SpriteEntries) { var spr = spriteEntry.Sprite; var so = new SerializedObject(spr); // 是否使用导出的贴图文件 string atlasName = spriteEntry.AtlasName; Texture2D atlasTexture; if (CustomAtlasConfig.ShouldUseOutputAtlasTexture(atlasName)) { atlasTexture = atlasEntry.OutputTexture; } else { atlasTexture = atlasEntry.Texture; } var alphaTexture = spriteEntry.AlphaTexture; // 获取散图属性 var rect = so.FindProperty("m_Rect").rectValue; var pivot = so.FindProperty("m_Pivot").vector2Value; var pixelsToUnits = so.FindProperty("m_PixelsToUnits").floatValue; var tightRect = so.FindProperty("m_RD.textureRect").rectValue; var originSettingsRaw = so.FindProperty("m_RD.settingsRaw").intValue; // 散图(tight)在散图(full rect)中的位置和宽高 var tightOffset = new Vector2(tightRect.x, tightRect.y); var tightWidth = tightRect.width; var tightHeight = tightRect.height; // 计算散图(full rect)在图集中的rect和offset var fullRectInAtlas = GetTextureFullRectInAtlas(atlasTexture, spriteEntry.Uvs, spriteEntry.AtlasUvs); var fullRectOffsetInAtlas = new Vector2(fullRectInAtlas.x, fullRectInAtlas.y); // 计算散图(tight)在图集中的rect var tightRectInAtlas = new Rect(fullRectInAtlas.x + tightOffset.x, fullRectInAtlas.y + tightOffset.y, tightWidth, tightHeight); // 计算uvTransform // x: Pixels To Unit X // y: 中心点在图集中的位置X // z: Pixels To Unit Y // w: 中心点在图集中的位置Y var uvTransform = new Vector4( pixelsToUnits, rect.width * pivot.x + fullRectOffsetInAtlas.x, pixelsToUnits, rect.height * pivot.y + fullRectOffsetInAtlas.y); // 计算settings // 0位:packed。1表示packed,0表示不packed // 1位:SpritePackingMode。0表示tight,1表示rectangle // 2-5位:SpritePackingRotation。0表示不旋转,1表示水平翻转,2表示竖直翻转,3表示180度旋转,4表示90度旋转 // 6位:SpriteMeshType。0表示full rect,1表示tight // 67 = SpriteMeshType(tight) + SpritePackingMode(rectangle) + packed var settingsRaw = 67; // 写入RenderData so.FindProperty("m_RD.texture").objectReferenceValue = atlasTexture; so.FindProperty("m_RD.alphaTexture").objectReferenceValue = alphaTexture; so.FindProperty("m_RD.textureRect").rectValue = tightRectInAtlas; so.FindProperty("m_RD.textureRectOffset").vector2Value = tightOffset; so.FindProperty("m_RD.atlasRectOffset").vector2Value = fullRectOffsetInAtlas; so.FindProperty("m_RD.settingsRaw").intValue = settingsRaw; so.FindProperty("m_RD.uvTransform").vector4Value = uvTransform; so.ApplyModifiedProperties(); // 备份原数据,用于恢复 spriteEntry.OriginTextureRect = tightRect; spriteEntry.OriginSettingsRaw = originSettingsRaw; } } }