// [UNITY-SKILL:SPRITEATLAS] using UnityEngine; using UnityEngine.U2D; using System.Collections.Generic; using UnityEditor.U2D; /// /// Demonstrates efficient querying of sprites from SpriteAtlases. /// Avoids expensive operations and unnecessary allocations. /// public static class QuerySpritesEfficientlyExample { /// /// Gets all sprites from an atlas efficiently. /// Uses the V2 GetPackables() method on runtime SpriteAtlas. /// public static Sprite[] GetSpritesFromAtlas(SpriteAtlas atlas) { if (atlas == null) { Debug.LogError("Cannot query: atlas is null"); return new Sprite[0]; } // Use GetPackables() - this is the V2 way Object[] packables = atlas.GetPackables(); // Filter to get only sprites var sprites = new List(); for (int i = 0; i < packables.Length; i++) { if (packables[i] is Sprite sprite) { sprites.Add(sprite); } } return sprites.ToArray(); } /// /// Gets a sprite by name from an atlas efficiently. /// Avoids iterating through all sprites on each call by caching the results. /// public static Sprite GetSpriteFromAtlas(SpriteAtlas atlas, string spriteName) { if (atlas == null) { Debug.LogError("Cannot query: atlas is null"); return null; } if (string.IsNullOrEmpty(spriteName)) { Debug.LogWarning("Cannot query: sprite name is null or empty"); return null; } // Get all sprites once Sprite[] sprites = GetSpritesFromAtlas(atlas); // Find matching sprite for (int i = 0; i < sprites.Length; i++) { if (sprites[i].name == spriteName) { return sprites[i]; } } Debug.LogWarning($"Sprite '{spriteName}' not found in atlas: {atlas.name}"); return null; } /// /// Queries multiple sprites by name from an atlas. /// More efficient than calling GetSpriteFromAtlas multiple times /// when you need to query many sprites at once. /// public static Sprite[] GetSpritesFromAtlas(SpriteAtlas atlas, string[] spriteNames) { if (atlas == null || spriteNames == null || spriteNames.Length == 0) return new Sprite[0]; // Get all sprites once Sprite[] allSprites = GetSpritesFromAtlas(atlas); // Create lookup dictionary for efficient searching var spriteLookup = new Dictionary(); for (int i = 0; i < allSprites.Length; i++) { spriteLookup[allSprites[i].name] = allSprites[i]; } // Query requested sprites var result = new List(spriteNames.Length); for (int i = 0; i < spriteNames.Length; i++) { if (spriteLookup.TryGetValue(spriteNames[i], out Sprite foundSprite)) { result.Add(foundSprite); } else { Debug.LogWarning($"Sprite '{spriteNames[i]}' not found in atlas: {atlas.name}"); } } return result.ToArray(); } /// /// Checks if an atlas contains a specific sprite by name. /// public static bool ContainsSprite(SpriteAtlas atlas, string spriteName) { if (atlas == null || string.IsNullOrEmpty(spriteName)) return false; Sprite[] sprites = GetSpritesFromAtlas(atlas); for (int i = 0; i < sprites.Length; i++) { if (sprites[i].name == spriteName) return true; } return false; } /// /// Gets the count of sprites in an atlas without loading all sprites. /// public static int GetSpriteCount(SpriteAtlas atlas) { if (atlas == null) return 0; Object[] packables = atlas.GetPackables(); int count = 0; for (int i = 0; i < packables.Length; i++) { if (packables[i] is Sprite) count++; } return count; } } /// /// Component that demonstrates efficient sprite querying. /// Caches queries for repeated access. /// public class EfficientSpriteQuery : MonoBehaviour { [SerializeField] private SpriteAtlas _atlas; private Dictionary _spriteCache; private bool _cacheInitialized = false; /// /// Initializes the cache with all sprites from the atlas. /// Call this once at startup for efficient repeated queries. /// public void InitializeCache() { if (_atlas == null) return; Sprite[] sprites = QuerySpritesEfficientlyExample.GetSpritesFromAtlas(_atlas); _spriteCache = new Dictionary(sprites.Length); for (int i = 0; i < sprites.Length; i++) { _spriteCache[sprites[i].name] = sprites[i]; } _cacheInitialized = true; Debug.Log($"Cached {sprites.Length} sprites from atlas: {_atlas.name}"); } /// /// Gets a sprite by name using the cached lookup. /// Much faster than querying the atlas directly for each call. /// public Sprite GetCachedSprite(string name) { if (!_cacheInitialized) { InitializeCache(); } if (_spriteCache.TryGetValue(name, out Sprite sprite)) { return sprite; } Debug.LogWarning($"Sprite '{name}' not found in cached atlas"); return null; } /// /// Gets a sprite by name, with optional cache initialization. /// public Sprite GetSprite(string name, bool initializeIfNeeded = true) { if (!_cacheInitialized && initializeIfNeeded) { InitializeCache(); } if (_spriteCache != null && _spriteCache.TryGetValue(name, out Sprite sprite)) { return sprite; } // Fallback to direct query if cache not available return QuerySpritesEfficientlyExample.GetSpriteFromAtlas(_atlas, name); } }