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; } } }
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 void FindAllEntries(BuildTarget buildTarget, List <SpriteEntry> spriteEntries, List <AtlasEntry> atlasEntries) { var platformString = GetPlatformString(buildTarget); foreach (var guid in AssetDatabase.FindAssets("t:Texture")) { var path = AssetDatabase.GUIDToAssetPath(guid); var importer = AssetImporter.GetAtPath(path) as TextureImporter; if (importer == null) { continue; } // 获取sprite列表 var sprites = AssetDatabase.LoadAllAssetRepresentationsAtPath(path) .Distinct() .OfType <Sprite>() .Where(x => x.packed) .ToArray(); for (var i = 0; i < sprites.Length; ++i) { var sprite = sprites[i]; Texture2D atlasTexture; string atlasName; Packer.GetAtlasDataForSprite(sprite, out atlasName, out atlasTexture); if (atlasTexture != null) { var entry = new SpriteEntry { Path = path, Sprite = sprite, Importer = importer, Texture = SpriteUtility.GetSpriteTexture(sprite, false), AtlasName = atlasName, Uvs = SpriteUtility.GetSpriteUVs(sprite, false), AtlasUvs = SpriteUtility.GetSpriteUVs(sprite, true), AtlasTexture = atlasTexture, }; spriteEntries.Add(entry); } } } // 获取atlas列表 var atlasGroups = from e in spriteEntries group e by e.AtlasTexture; foreach (var atlasGroup in atlasGroups) { var tex = atlasGroup.Key; var texName = tex.name; // 检查是否需要分离alpha通道 var atlasName = string.Empty; var needSeparateAlpha = false; foreach (var spriteEntry in atlasGroup) { var importer = spriteEntry.Importer; atlasName = importer.spritePackingTag; if (!string.IsNullOrEmpty(atlasName)) { var settings = importer.GetPlatformTextureSettings(platformString); var format = settings.format; if (format == TextureImporterFormat.Automatic) { format = importer.GetAutomaticFormat(platformString); } needSeparateAlpha = TextureUtility.IsTransparent(format); } } if (CustomAtlasConfig.ShouldKeepAlpha(atlasName)) { needSeparateAlpha = false; } var entry = new AtlasEntry { Name = texName, Texture = tex, SpriteEntries = atlasGroup.ToList(), NeedSeparateAlpha = needSeparateAlpha, }; atlasEntries.Add(entry); } }