// [UNITY-SKILL:SPRITEATLAS] using UnityEditor.U2D; using UnityEngine; using Unity.Collections; using System.Collections.Generic; using System.Linq; /// /// Size-optimized sprite packer that places larger sprites first. /// Uses a simple bin-packing approach to minimize atlas space usage. /// public class SizeOptimizedPacker : ScriptablePacker { /// Maximum atlas size (width and height) in pixels public int atlasSize = 2048; /// Padding between sprites in pixels public int padding = 4; /// /// Packs sprites with larger ones first for better space utilization. /// Sorts sprites by area (width * height) and places them using first-fit bin packing. /// public override bool Pack(SpriteAtlasPackingSettings config, SpriteAtlasTextureSettings setting, PackerData input) { NativeArray sprites = input.spriteData; NativeArray textures = input.textureData; // Create sorted list by area (largest first) var sortedIndices = new List(); for (int i = 0; i < sprites.Length; i++) { sortedIndices.Add(i); } sortedIndices = sortedIndices .OrderByDescending(i => { var sprite = sprites[i]; return sprite.rect.width * sprite.rect.height; }) .ToList(); // Simple bin packing int currentX = padding; int currentY = padding; int maxHeightInRow = 0; foreach (int idx in sortedIndices) { SpriteData sprite = sprites[idx]; int spriteWidth = sprite.rect.width; int spriteHeight = sprite.rect.height; // Check if we need a new row if (currentX + spriteWidth + padding > atlasSize) { currentX = padding; currentY += maxHeightInRow + padding; maxHeightInRow = 0; } // Check if atlas is full if (currentY + spriteHeight + padding > atlasSize) { Debug.LogError("Atlas size exceeded. Increase atlas size or reduce sprite count."); return false; } // Set output sprite.output.x = currentX; sprite.output.y = currentY; sprite.output.page = 0; sprite.output.rot = PackTransform.None; // Update position for next sprite currentX += spriteWidth + padding; maxHeightInRow = Mathf.Max(maxHeightInRow, spriteHeight); sprites[idx] = sprite; } return true; } }