using System.Collections.Generic; using Superlazy; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.ResourceManagement.AsyncOperations; using UnityEngine.ResourceManagement.ResourceLocations; using UnityEngine.ResourceManagement.ResourceProviders; using UnityEngine.SceneManagement; using UnityEngine.U2D; public static class SLResources { private static Dictionary> unusedResourceObjects; private static Dictionary> unusedPrefabs; private static Transform unusedRoot; public static SLResourceObject CreateInstance(string prefabName, Transform parent = null) { if (unusedResourceObjects != null && unusedResourceObjects.ContainsKey(prefabName) && unusedResourceObjects[prefabName].Count > 0) { var instance = unusedResourceObjects[prefabName].Dequeue(); instance.transform.SetParent(parent, false); return instance; } else { var obj = GetPrefab(prefabName); if (obj == null) { SLLog.Error($"Can't Find Preafb. [{prefabName}]"); return null; } var objectInstance = Object.Instantiate(obj, parent); objectInstance.name = prefabName; var instance = objectInstance.GetComponent(); if (instance == null) { SLLog.Error($"Can't Find SLResourceObject. [{prefabName}]"); return null; } return instance; } } internal static void DestroyInstance(this SLResourceObject go) { unusedResourceObjects ??= new Dictionary>(); if (unusedRoot == null) { unusedRoot = new GameObject("UnusedInstance").transform; unusedRoot.gameObject.SetActive(false); } go.transform.SetParent(unusedRoot, false); if (unusedResourceObjects.ContainsKey(go.name) == false) { unusedResourceObjects.Add(go.name, new Queue()); } unusedResourceObjects[go.name].Enqueue(go); } public static GameObject CreatePrefabInstance(string prefabName, Transform parent = null) { if (unusedPrefabs != null && unusedPrefabs.ContainsKey(prefabName) && unusedPrefabs[prefabName].Count > 0) { var instance = unusedPrefabs[prefabName].Dequeue(); instance.transform.SetParent(parent, false); return instance; } else { var obj = GetPrefab(prefabName); if (obj == null) { SLLog.Error($"Can't Find Preafb. [{prefabName}]"); return null; } var instance = Object.Instantiate(obj, parent); instance.name = prefabName; return instance; } } public static void Destroy(this GameObject go) { unusedPrefabs ??= new Dictionary>(); if (unusedRoot == null) { unusedRoot = new GameObject("UnusedInstance").transform; unusedRoot.gameObject.SetActive(false); } go.transform.SetParent(unusedRoot, false); if (unusedPrefabs.ContainsKey(go.name) == false) { unusedPrefabs.Add(go.name, new Queue()); } unusedPrefabs[go.name].Enqueue(go); } public static GameObject GetPrefab(string prefabName) { if (string.IsNullOrEmpty(prefabName)) return null; var obj = Load(prefabName); return obj; } public static Sprite GetSprite(string spritePath) { if (string.IsNullOrEmpty(spritePath)) return null; if (spritePath.Contains('/') == false) return null; //TODO: 문자열 분할이 일어나지 않게끔 캐싱 var seperateIdx = spritePath.LastIndexOf('/'); var atlasPath = spritePath.Substring(0, seperateIdx); var spriteName = spritePath.Substring(seperateIdx + 1); { // check big var bigPath = $"{atlasPath}_{spriteName}"; if (AddressableResourceExists(bigPath)) { return Load(bigPath).GetSprite(spriteName); } } return Load(atlasPath).GetSprite(spriteName); } public static RuntimeAnimatorController GetAnimatorController(string controler) { return Load(controler); } public static IList LoadAll(string path) where T : Object { return Addressables.LoadAssetsAsync(path, (t) => { }).WaitForCompletion(); } public static T Load(string resourceName) where T : Object { #if UNITY_EDITOR try { #endif //if (AddressableResourceExists(resourceName) == false) return default; // TODO: 원인 파악해서 에디터에서 에러 정상발생하도록 수정 return Addressables.LoadAssetAsync(resourceName).WaitForCompletion(); #if UNITY_EDITOR } catch { SLLog.Error($"Can't Find Resource. [{resourceName}]"); return default; } #endif } public static AsyncOperationHandle LoadScene(string resourceName, LoadSceneMode mode, bool active = false) { #if UNITY_EDITOR try { #endif // if (AddressableResourceExists(resourceName) == false) return default; // TODO: 원인 파악해서 에디터에서 에러 정상발생하도록 수정 return Addressables.LoadSceneAsync(resourceName, mode, active); #if UNITY_EDITOR } catch { SLLog.Error($"Can't Find Resource. [{resourceName}]"); return default; } #endif } public static AsyncOperationHandle UnloadScene(SceneInstance inst) { return Addressables.UnloadSceneAsync(inst); } private static bool AddressableResourceExists(object key) // TODO: 성능이슈 개선필요 // TODO: 원인 파악해서 에디터에서 에러 정상발생하도록 수정 { foreach (var l in Addressables.ResourceLocators) { if (l.Locate(key, typeof(T), out var _)) return true; } return false; } }