ProjectDDD/Packages/SLUnity/SLResource.cs
2025-07-08 19:46:31 +09:00

200 lines
6.3 KiB
C#

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<string, Queue<SLResourceObject>> unusedResourceObjects;
private static Dictionary<string, Queue<GameObject>> 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<SLResourceObject>();
if (instance == null)
{
SLLog.Error($"Can't Find SLResourceObject. [{prefabName}]");
return null;
}
return instance;
}
}
internal static void DestroyInstance(this SLResourceObject go)
{
unusedResourceObjects ??= new Dictionary<string, Queue<SLResourceObject>>();
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<SLResourceObject>());
}
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<string, Queue<GameObject>>();
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<GameObject>());
}
unusedPrefabs[go.name].Enqueue(go);
}
public static GameObject GetPrefab(string prefabName)
{
if (string.IsNullOrEmpty(prefabName)) return null;
var obj = Load<GameObject>(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<SpriteAtlas>(bigPath))
{
return Load<SpriteAtlas>(bigPath).GetSprite(spriteName);
}
}
return Load<SpriteAtlas>(atlasPath).GetSprite(spriteName);
}
public static RuntimeAnimatorController GetAnimatorController(string controler)
{
return Load<RuntimeAnimatorController>(controler);
}
public static IList<T> LoadAll<T>(string path) where T : Object
{
return Addressables.LoadAssetsAsync<T>(path, (t) => { }).WaitForCompletion();
}
public static T Load<T>(string resourceName) where T : Object
{
#if UNITY_EDITOR
try
{
#endif
//if (AddressableResourceExists<T>(resourceName) == false) return default; // TODO: 원인 파악해서 에디터에서 에러 정상발생하도록 수정
return Addressables.LoadAssetAsync<T>(resourceName).WaitForCompletion();
#if UNITY_EDITOR
}
catch
{
SLLog.Error($"Can't Find Resource. [{resourceName}]");
return default;
}
#endif
}
public static AsyncOperationHandle<SceneInstance> LoadScene(string resourceName, LoadSceneMode mode, bool active = false)
{
#if UNITY_EDITOR
try
{
#endif
// if (AddressableResourceExists<SceneInstance>(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<SceneInstance> UnloadScene(SceneInstance inst)
{
return Addressables.UnloadSceneAsync(inst);
}
private static bool AddressableResourceExists<T>(object key) // TODO: 성능이슈 개선필요 // TODO: 원인 파악해서 에디터에서 에러 정상발생하도록 수정
{
foreach (var l in Addressables.ResourceLocators)
{
if (l.Locate(key, typeof(T), out var _))
return true;
}
return false;
}
}