Addressable기능 AssetManager로 통합
This commit is contained in:
parent
a1c33cdaf5
commit
db5de56b3b
@ -45,3 +45,4 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
_persistent: 1
|
||||
_enableDebugLog: 1
|
||||
|
@ -45,3 +45,4 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
_persistent: 1
|
||||
_inventoryTestDataSo: {fileID: 11400000, guid: 29d0dee3b70fbc44d992ea47012bc366, type: 2}
|
||||
|
BIN
Assets/_DDD/_ScriptAssets/So/ManagerDefinitionSo.asset
(Stored with Git LFS)
BIN
Assets/_DDD/_ScriptAssets/So/ManagerDefinitionSo.asset
(Stored with Git LFS)
Binary file not shown.
@ -1,10 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor.AddressableAssets;
|
||||
#endif
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
using UnityEngine.ResourceManagement.AsyncOperations;
|
||||
@ -15,7 +11,34 @@ namespace DDD
|
||||
{
|
||||
public class AssetManager : Singleton<AssetManager>, IManager
|
||||
{
|
||||
private static readonly Dictionary<string, AsyncOperationHandle> _cachedHandles = new();
|
||||
private struct CachedAsset
|
||||
{
|
||||
public AsyncOperationHandle Handle;
|
||||
public int ReferenceCount;
|
||||
|
||||
public CachedAsset(AsyncOperationHandle handle, int count = 1)
|
||||
{
|
||||
Handle = handle;
|
||||
ReferenceCount = count;
|
||||
}
|
||||
}
|
||||
|
||||
private struct CachedScene
|
||||
{
|
||||
public AsyncOperationHandle<SceneInstance> Handle;
|
||||
public int ReferenceCount;
|
||||
|
||||
public CachedScene(AsyncOperationHandle<SceneInstance> handle, int count = 1)
|
||||
{
|
||||
Handle = handle;
|
||||
ReferenceCount = count;
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField] private bool _enableDebugLog = false;
|
||||
|
||||
private readonly Dictionary<string, CachedAsset> _cachedAssets = new();
|
||||
private readonly Dictionary<string, CachedScene> _cachedScenes = new();
|
||||
|
||||
protected override void OnApplicationQuit()
|
||||
{
|
||||
@ -24,110 +47,284 @@ protected override void OnApplicationQuit()
|
||||
ReleaseAllCached();
|
||||
}
|
||||
|
||||
public void PreInit()
|
||||
{
|
||||
|
||||
}
|
||||
public void PreInit() { }
|
||||
|
||||
public async Task Init()
|
||||
{
|
||||
await Addressables.InitializeAsync().Task;
|
||||
}
|
||||
|
||||
public void PostInit()
|
||||
{
|
||||
public void PostInit() { }
|
||||
|
||||
private string GetSafeAssetName(AssetReference assetReference)
|
||||
{
|
||||
var editorAssetName = assetReference.editorAsset.name;
|
||||
if (string.IsNullOrWhiteSpace(editorAssetName) == false) return editorAssetName;
|
||||
|
||||
return assetReference.ToString();
|
||||
}
|
||||
|
||||
public static async Task<T> LoadAsset<T>(string key) where T : UnityEngine.Object
|
||||
public async Task<T> LoadAssetAsync<T>(AssetReference assetReference) where T : Object
|
||||
{
|
||||
if (_cachedHandles.TryGetValue(key, out var handle))
|
||||
var guidKey = assetReference.AssetGUID;
|
||||
|
||||
if (_cachedAssets.TryGetValue(guidKey, out var cachedAsset))
|
||||
{
|
||||
if (handle.IsValid() && handle.Result is T result)
|
||||
if (cachedAsset.Handle.IsValid() && cachedAsset.Handle.Result is T result)
|
||||
{
|
||||
cachedAsset.ReferenceCount++;
|
||||
_cachedAssets[guidKey] = cachedAsset;
|
||||
|
||||
if (_enableDebugLog) Debug.Log($"[AssetManager] 에셋 참조 카운트 증가: {GetSafeAssetName(assetReference)} -> {cachedAsset.ReferenceCount}\n실제 키 값: {guidKey}");
|
||||
return result;
|
||||
|
||||
Debug.LogWarning($"[AssetManager] Type mismatch or invalid handle for key: {key}");
|
||||
return handle.Result as T;
|
||||
}
|
||||
|
||||
// ✅ 새로 로드
|
||||
var newHandle = Addressables.LoadAssetAsync<T>(key);
|
||||
_cachedAssets.Remove(guidKey);
|
||||
Debug.LogWarning($"[AssetManager] 무효한 핸들 제거됨: {GetSafeAssetName(assetReference)}\n실제 키 값: {guidKey}");
|
||||
}
|
||||
|
||||
var newHandle = Addressables.LoadAssetAsync<T>(guidKey);
|
||||
await newHandle.Task;
|
||||
|
||||
if (newHandle.Status == AsyncOperationStatus.Succeeded)
|
||||
{
|
||||
_cachedHandles[key] = newHandle;
|
||||
_cachedAssets[guidKey] = new CachedAsset(newHandle, 1);
|
||||
if (_enableDebugLog) Debug.Log($"[AssetManager] 에셋 로드 및 캐싱 완료: {GetSafeAssetName(assetReference)} (참조수: {_cachedAssets[guidKey].ReferenceCount})\n실제 키 값: {guidKey}");
|
||||
return newHandle.Result;
|
||||
}
|
||||
|
||||
Debug.LogError($"[AssetManager] Failed to load asset: {key}");
|
||||
if (newHandle.IsValid())
|
||||
{
|
||||
Addressables.Release(newHandle);
|
||||
}
|
||||
|
||||
Debug.LogError($"[AssetManager] 에셋 로드 실패: {GetSafeAssetName(assetReference)}\n실제 키 값: {guidKey}");
|
||||
return null;
|
||||
}
|
||||
|
||||
public static async Task<List<T>> LoadAssetsByLabel<T>(string label) where T : UnityEngine.Object
|
||||
/// <summary>
|
||||
/// ScriptSingleton을 위한 동기 로딩
|
||||
/// </summary>
|
||||
public T LoadAsset<T>(string key) where T : Object
|
||||
{
|
||||
var handle = Addressables.LoadAssetsAsync<T>(label, null);
|
||||
if (_cachedAssets.TryGetValue(key, out var cachedAsset))
|
||||
{
|
||||
if (cachedAsset.Handle.IsValid() && cachedAsset.Handle.Result is T result)
|
||||
{
|
||||
cachedAsset.ReferenceCount++;
|
||||
_cachedAssets[key] = cachedAsset;
|
||||
|
||||
if (_enableDebugLog) Debug.Log($"[AssetManager] 동기 로딩 - 에셋 참조 카운트 증가: {key} -> {cachedAsset.ReferenceCount}");
|
||||
return result;
|
||||
}
|
||||
|
||||
_cachedAssets.Remove(key);
|
||||
Debug.LogWarning($"[AssetManager] 무효한 핸들 제거됨: {key}");
|
||||
}
|
||||
|
||||
var handle = Addressables.LoadAssetAsync<T>(key);
|
||||
var loaded = handle.WaitForCompletion();
|
||||
|
||||
if (handle.Status == AsyncOperationStatus.Succeeded)
|
||||
{
|
||||
_cachedAssets[key] = new CachedAsset(handle, 1);
|
||||
if (_enableDebugLog) Debug.Log($"[AssetManager] 동기 로딩 - 에셋 로드 및 캐싱 완료: {key} (참조수: {key})");
|
||||
return loaded;
|
||||
}
|
||||
|
||||
if (handle.IsValid())
|
||||
{
|
||||
Addressables.Release(handle);
|
||||
}
|
||||
|
||||
Debug.LogError($"[AssetManager] 동기 로딩 - 에셋 로드 실패: {key}");
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<List<T>> LoadAssetsByLabel<T>(string label) where T : Object
|
||||
{
|
||||
if (_cachedAssets.TryGetValue(label, out var cachedAsset))
|
||||
{
|
||||
if (cachedAsset.Handle.IsValid() && cachedAsset.Handle.Result is IList<T> cachedResult)
|
||||
{
|
||||
cachedAsset.ReferenceCount++;
|
||||
_cachedAssets[label] = cachedAsset;
|
||||
|
||||
if (_enableDebugLog) Debug.Log($"[AssetManager] 라벨 에셋 참조 카운트 증가: {label} -> {cachedAsset.ReferenceCount}");
|
||||
return cachedResult.ToList();
|
||||
}
|
||||
|
||||
_cachedAssets.Remove(label);
|
||||
if (_enableDebugLog) Debug.LogWarning($"[AssetManager] 무효한 라벨 핸들 제거됨: {label}");
|
||||
}
|
||||
|
||||
var handle = Addressables.LoadAssetsAsync<T>(label);
|
||||
await handle.Task;
|
||||
|
||||
if (handle.Status == AsyncOperationStatus.Succeeded)
|
||||
{
|
||||
_cachedAssets[label] = new CachedAsset(handle, 1);
|
||||
if (_enableDebugLog) Debug.Log($"[AssetManager] 라벨 에셋 로드 및 캐싱 완료: {label} (참조수: {_cachedAssets[label].ReferenceCount})");
|
||||
return handle.Result.ToList();
|
||||
}
|
||||
|
||||
Debug.LogError($"[AssetManager] Failed to load assets with label: {label}");
|
||||
if (handle.IsValid())
|
||||
{
|
||||
Addressables.Release(handle);
|
||||
}
|
||||
|
||||
Debug.LogError($"[AssetManager] 라벨 에셋 로드 실패: {label}");
|
||||
return new List<T>();
|
||||
}
|
||||
|
||||
public static async Task<SceneInstance> LoadScene(AssetReference assetReference, LoadSceneMode mode = LoadSceneMode.Additive, bool activateOnLoad = true)
|
||||
public void ReleaseAsset(AssetReference assetReference)
|
||||
{
|
||||
var guidKey = assetReference.AssetGUID;
|
||||
|
||||
if (_cachedAssets.TryGetValue(guidKey, out var cachedAsset))
|
||||
{
|
||||
cachedAsset.ReferenceCount--;
|
||||
|
||||
if (cachedAsset.ReferenceCount <= 0)
|
||||
{
|
||||
if (cachedAsset.Handle.IsValid())
|
||||
{
|
||||
Addressables.Release(cachedAsset.Handle);
|
||||
if (_enableDebugLog) Debug.Log($"[AssetManager] 에셋 실제 해제됨: {GetSafeAssetName(assetReference)}\n실제 키 값: {guidKey}");
|
||||
}
|
||||
_cachedAssets.Remove(guidKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
_cachedAssets[guidKey] = cachedAsset;
|
||||
if (_enableDebugLog) Debug.Log($"[AssetManager] 에셋 참조 카운트 감소: {GetSafeAssetName(assetReference)} -> {cachedAsset.ReferenceCount}\n실제 키 값: {guidKey}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_enableDebugLog) Debug.LogWarning($"[AssetManager] 캐시에서 에셋을 찾을 수 없음: {GetSafeAssetName(assetReference)}\n실제 키 값: {guidKey}");
|
||||
}
|
||||
}
|
||||
|
||||
public void ReleaseAsset(string key)
|
||||
{
|
||||
if (_cachedAssets.TryGetValue(key, out var cachedAsset))
|
||||
{
|
||||
cachedAsset.ReferenceCount--;
|
||||
|
||||
if (cachedAsset.ReferenceCount <= 0)
|
||||
{
|
||||
if (cachedAsset.Handle.IsValid())
|
||||
{
|
||||
Addressables.Release(cachedAsset.Handle);
|
||||
if (_enableDebugLog) Debug.Log($"[AssetManager] 에셋 실제 해제됨: {key}");
|
||||
}
|
||||
_cachedAssets.Remove(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
_cachedAssets[key] = cachedAsset;
|
||||
if (_enableDebugLog) Debug.Log($"[AssetManager] 에셋 참조 카운트 감소: {key} -> {cachedAsset.ReferenceCount}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_enableDebugLog) Debug.LogWarning($"[AssetManager] 캐시에서 에셋을 찾을 수 없음: {key}");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<SceneInstance> LoadScene(AssetReference assetReference, LoadSceneMode mode = LoadSceneMode.Additive, bool activateOnLoad = true)
|
||||
{
|
||||
var guidKey = assetReference.AssetGUID;
|
||||
|
||||
if (_cachedScenes.TryGetValue(guidKey, out var cachedScene))
|
||||
{
|
||||
if (cachedScene.Handle.IsValid())
|
||||
{
|
||||
cachedScene.ReferenceCount++;
|
||||
_cachedScenes[guidKey] = cachedScene;
|
||||
|
||||
if (_enableDebugLog) Debug.Log($"[AssetManager] 씬 참조 카운트 증가: {GetSafeAssetName(assetReference)} -> {cachedScene.ReferenceCount}\n실제 키 값: {guidKey}");
|
||||
return cachedScene.Handle.Result;
|
||||
}
|
||||
|
||||
_cachedScenes.Remove(guidKey);
|
||||
if (_enableDebugLog) Debug.LogWarning($"[AssetManager] 무효한 씬 핸들 제거됨: {GetSafeAssetName(assetReference)}\n실제 키 값: {guidKey}");
|
||||
}
|
||||
|
||||
var handle = Addressables.LoadSceneAsync(assetReference, mode, activateOnLoad);
|
||||
await handle.Task;
|
||||
|
||||
if (handle.Status == AsyncOperationStatus.Succeeded)
|
||||
{
|
||||
_cachedScenes[guidKey] = new CachedScene(handle, 1);
|
||||
var sceneName = handle.Result.Scene.name;
|
||||
if (_enableDebugLog) Debug.Log($"[AssetManager] 씬 로드 및 캐싱 완료: {sceneName} (참조수: {_cachedScenes[guidKey].ReferenceCount})\n실제 키 값: {guidKey}");
|
||||
return handle.Result;
|
||||
}
|
||||
|
||||
Debug.LogError($"Scene load failed: {assetReference}");
|
||||
if (handle.IsValid())
|
||||
{
|
||||
Addressables.UnloadSceneAsync(handle);
|
||||
}
|
||||
|
||||
Debug.LogError($"[AssetManager] 씬 로드 실패: {GetSafeAssetName(assetReference)}\n실제 키 값: {guidKey}");
|
||||
return default;
|
||||
}
|
||||
|
||||
public static async Task UnloadScene(SceneInstance sceneInstance)
|
||||
public async Task UnloadScene(AssetReference assetReference)
|
||||
{
|
||||
var handle = Addressables.UnloadSceneAsync(sceneInstance);
|
||||
await handle.Task;
|
||||
var guidKey = assetReference.AssetGUID;
|
||||
|
||||
if (_cachedScenes.TryGetValue(guidKey, out var cachedScene))
|
||||
{
|
||||
cachedScene.ReferenceCount--;
|
||||
|
||||
if (cachedScene.ReferenceCount <= 0)
|
||||
{
|
||||
if (cachedScene.Handle.IsValid())
|
||||
{
|
||||
var sceneName = cachedScene.Handle.Result.Scene.name;
|
||||
await Addressables.UnloadSceneAsync(cachedScene.Handle).Task;
|
||||
if (_enableDebugLog) Debug.Log($"[AssetManager] 씬 실제 언로드됨: {sceneName}\n실제 키 값: {guidKey}");
|
||||
}
|
||||
|
||||
public static void ReleaseAllCached()
|
||||
_cachedScenes.Remove(guidKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_cachedHandles.Count == 0) return;
|
||||
|
||||
foreach (var kvp in _cachedHandles)
|
||||
{
|
||||
var handle = kvp.Value;
|
||||
if (handle.IsValid())
|
||||
{
|
||||
Addressables.Release(handle);
|
||||
//Debug.Log($"[AssetManager] Released handle for key: {kvp.Key}");
|
||||
_cachedScenes[guidKey] = cachedScene;
|
||||
if (_enableDebugLog) Debug.Log($"[AssetManager] 씬 참조 카운트 감소: {GetSafeAssetName(assetReference)} -> {cachedScene.ReferenceCount}\n실제 키 값: {guidKey}");
|
||||
}
|
||||
}
|
||||
_cachedHandles.Clear();
|
||||
|
||||
Debug.Log("[AssetManager] 모든 캐시된 Addressable 리소스를 해제했습니다.");
|
||||
else
|
||||
{
|
||||
if (_enableDebugLog) Debug.LogWarning($"[AssetManager] 캐시에서 씬을 찾을 수 없음: {GetSafeAssetName(assetReference)}\n실제 키 값: {guidKey}");
|
||||
}
|
||||
}
|
||||
|
||||
public static bool HasLabel(string addressKey, string label)
|
||||
public void ReleaseAllCached()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
var settings = AddressableAssetSettingsDefaultObject.Settings;
|
||||
if (settings == null) return false;
|
||||
foreach (var kvp in _cachedAssets)
|
||||
{
|
||||
var cachedAsset = kvp.Value;
|
||||
if (cachedAsset.Handle.IsValid())
|
||||
{
|
||||
Addressables.Release(cachedAsset.Handle);
|
||||
}
|
||||
}
|
||||
_cachedAssets.Clear();
|
||||
|
||||
var entry = settings.groups
|
||||
.SelectMany(g => g.entries)
|
||||
.FirstOrDefault(e => e.address == addressKey);
|
||||
foreach (var kvp in _cachedScenes)
|
||||
{
|
||||
var cachedScene = kvp.Value;
|
||||
if (cachedScene.Handle.IsValid())
|
||||
{
|
||||
Addressables.UnloadSceneAsync(cachedScene.Handle);
|
||||
}
|
||||
}
|
||||
_cachedScenes.Clear();
|
||||
|
||||
if (entry == null) return false;
|
||||
|
||||
return entry.labels.Contains(label);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
if (_enableDebugLog) Debug.Log("[AssetManager] 모든 캐시된 Addressable 리소스를 강제 해제했습니다.");
|
||||
}
|
||||
}
|
||||
}
|
@ -32,7 +32,7 @@ public void PostInit()
|
||||
|
||||
private async Task LoadAllGameDataSo()
|
||||
{
|
||||
var soList = await AssetManager.LoadAssetsByLabel<ScriptableObject>(SoLabel);
|
||||
var soList = await AssetManager.Instance.LoadAssetsByLabel<ScriptableObject>(SoLabel);
|
||||
|
||||
foreach (var so in soList)
|
||||
{
|
||||
@ -45,7 +45,7 @@ private async Task LoadAllGameDataSo()
|
||||
|
||||
private async Task LoadSpriteAtlas()
|
||||
{
|
||||
List<SpriteAtlas> spriteAtlases = await AssetManager.LoadAssetsByLabel<SpriteAtlas>(DataConstants.AtlasLabel);
|
||||
List<SpriteAtlas> spriteAtlases = await AssetManager.Instance.LoadAssetsByLabel<SpriteAtlas>(DataConstants.AtlasLabel);
|
||||
_spriteAtlas = new Dictionary<string, Sprite>(spriteAtlases.Count);
|
||||
|
||||
foreach (var atlas in spriteAtlases)
|
||||
|
@ -22,18 +22,8 @@ public async Task LoadData()
|
||||
return;
|
||||
}
|
||||
|
||||
var gameLocalizationDataHandle = _gameLocalizationData.LoadAssetAsync<GameLocalizationData>();
|
||||
var test = AssetManager.LoadAsset<GameLocalizationData>(_gameLocalizationData.AssetGUID);
|
||||
var popupUiDataHandle = _uiData.LoadAssetAsync<UiData>();
|
||||
|
||||
await gameLocalizationDataHandle.Task;
|
||||
await popupUiDataHandle.Task;
|
||||
|
||||
LocalizationData = gameLocalizationDataHandle.Result;
|
||||
UiData = popupUiDataHandle.Result;
|
||||
|
||||
Debug.Assert(LocalizationData != null, "GameLocalizationData is null");
|
||||
Debug.Assert(UiData != null, "UiData is null");
|
||||
LocalizationData = await AssetManager.Instance.LoadAssetAsync<GameLocalizationData>(_gameLocalizationData);
|
||||
UiData = await AssetManager.Instance.LoadAssetAsync<UiData>(_uiData);
|
||||
|
||||
_isLoaded = true;
|
||||
}
|
||||
@ -42,7 +32,15 @@ private void OnDisable()
|
||||
{
|
||||
if (_isLoaded == false) return;
|
||||
|
||||
_gameLocalizationData.ReleaseAsset();
|
||||
var assetManager = AssetManager.Instance;
|
||||
if (!assetManager) return;
|
||||
|
||||
AssetManager.Instance.ReleaseAsset(_gameLocalizationData);
|
||||
AssetManager.Instance.ReleaseAsset(_uiData);
|
||||
|
||||
LocalizationData = null;
|
||||
UiData = null;
|
||||
|
||||
_isLoaded = false;
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ public async Task PreloadAll()
|
||||
continue;
|
||||
}
|
||||
|
||||
var instance = await AssetManager.LoadScene(flowAssetPair.Value, activateOnLoad:false);
|
||||
var instance = await AssetManager.Instance.LoadScene(flowAssetPair.Value, activateOnLoad:false);
|
||||
if (!instance.Scene.IsValid())
|
||||
{
|
||||
Debug.LogError($"[SceneManager] {flowAssetPair.Key}의 씬 로딩 실패");
|
||||
@ -114,7 +114,7 @@ public async Task PreloadScene(GameFlowState gameFlowState)
|
||||
return;
|
||||
}
|
||||
|
||||
var loadedInstance = await AssetManager.LoadScene(assetRef);
|
||||
var loadedInstance = await AssetManager.Instance.LoadScene(assetRef);
|
||||
if (!loadedInstance.Scene.IsValid())
|
||||
{
|
||||
Debug.LogError($"[SceneManager] {gameFlowState}의 씬 로딩 실패");
|
||||
@ -170,7 +170,7 @@ public async Task UnloadScene(GameFlowState gameFlowState)
|
||||
}
|
||||
|
||||
_loadedSceneDatas.Remove(gameFlowState);
|
||||
await AssetManager.UnloadScene(sceneData.SceneInstance.Value);
|
||||
await AssetManager.Instance.UnloadScene(assetRef);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@ public class InventoryManager : Singleton<InventoryManager>, IManager
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[Title("테스트용")]
|
||||
[SerializeField]
|
||||
private InventoryTestDataSo _inventoryTestDataSo;
|
||||
#endif
|
||||
|
||||
@ -62,12 +63,8 @@ private void InitializeItemData()
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private async void ApplyEditorTestData()
|
||||
private void ApplyEditorTestData()
|
||||
{
|
||||
_inventoryTestDataSo = await AssetManager.LoadAsset<InventoryTestDataSo>(DataConstants.InventoryTestDataSo);
|
||||
|
||||
if (_inventoryTestDataSo == null || !_inventoryTestDataSo.UseTestData) return;
|
||||
|
||||
foreach (var entry in _inventoryTestDataSo.TestItems)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(entry.ItemId)) continue;
|
||||
|
@ -28,7 +28,6 @@ public struct CustomerSpawnArgs
|
||||
public class CustomerFactory : ICustomerFactory
|
||||
{
|
||||
private GameObject _customerPrefab;
|
||||
private AsyncOperationHandle<GameObject> _customerPrefabHandle;
|
||||
|
||||
public async Task<GameObject> CreateAsync(CustomerSpawnArgs args)
|
||||
{
|
||||
@ -66,25 +65,12 @@ private async Task LoadCustomerAsset()
|
||||
return;
|
||||
}
|
||||
|
||||
_customerPrefabHandle = customerDataAsset.CustomerPrefab.LoadAssetAsync<GameObject>();
|
||||
await _customerPrefabHandle.Task;
|
||||
|
||||
if (_customerPrefabHandle.Result == null)
|
||||
{
|
||||
Debug.LogError("[CustomerFactory] Failed to load customer prefab from AssetReference.");
|
||||
return;
|
||||
}
|
||||
|
||||
_customerPrefab = _customerPrefabHandle.Result;
|
||||
Debug.Log("[CustomerFactory] Customer prefab loaded successfully.");
|
||||
_customerPrefab = await AssetManager.Instance.LoadAssetAsync<GameObject>(customerDataAsset.CustomerPrefab);
|
||||
}
|
||||
|
||||
public void UnloadAssets()
|
||||
{
|
||||
if (_customerPrefabHandle.IsValid())
|
||||
{
|
||||
Addressables.Release(_customerPrefabHandle);
|
||||
}
|
||||
AssetManager.Instance.ReleaseAsset(RestaurantData.Instance.CustomerData.CustomerPrefab);
|
||||
_customerPrefab = null;
|
||||
Debug.Log("[CustomerFactory] Customer prefab unloaded.");
|
||||
}
|
||||
|
@ -26,27 +26,10 @@ public async Task LoadData()
|
||||
return;
|
||||
}
|
||||
|
||||
var restaurantPlayerDataHandle = _restaurantPlayerData.LoadAssetAsync<RestaurantPlayerData>();
|
||||
var restaurantManagementDataHandle = _restaurantManagementData.LoadAssetAsync<RestaurantManagementData>();
|
||||
var restaurantRunDataHandle = _restaurantRunData.LoadAssetAsync<RestaurantRunData>();
|
||||
var restaurantCustomerDataHandle = _restaurantCustomerData.LoadAssetAsync<RestaurantCustomerData>();
|
||||
|
||||
await Task.WhenAll(
|
||||
restaurantPlayerDataHandle.Task,
|
||||
restaurantManagementDataHandle.Task,
|
||||
restaurantRunDataHandle.Task,
|
||||
restaurantCustomerDataHandle.Task
|
||||
);
|
||||
|
||||
PlayerData = restaurantPlayerDataHandle.Result;
|
||||
ManagementData = restaurantManagementDataHandle.Result;
|
||||
RunData = restaurantRunDataHandle.Result;
|
||||
CustomerData = restaurantCustomerDataHandle.Result;
|
||||
|
||||
Debug.Assert(PlayerData != null, "RestaurantPlayerData is null");
|
||||
Debug.Assert(ManagementData != null, "RestaurantManagementData is null");
|
||||
Debug.Assert(RunData != null, "RestaurantRunData is null");
|
||||
Debug.Assert(CustomerData != null, "RestaurantCustomerData is null");
|
||||
PlayerData = await AssetManager.Instance.LoadAssetAsync<RestaurantPlayerData>(_restaurantPlayerData);
|
||||
ManagementData = await AssetManager.Instance.LoadAssetAsync<RestaurantManagementData>(_restaurantManagementData);
|
||||
RunData = await AssetManager.Instance.LoadAssetAsync<RestaurantRunData>(_restaurantRunData);
|
||||
CustomerData = await AssetManager.Instance.LoadAssetAsync<RestaurantCustomerData>(_restaurantCustomerData);
|
||||
|
||||
_isLoaded = true;
|
||||
}
|
||||
@ -55,10 +38,18 @@ private void OnDisable()
|
||||
{
|
||||
if (_isLoaded == false) return;
|
||||
|
||||
_restaurantPlayerData.ReleaseAsset();
|
||||
_restaurantManagementData.ReleaseAsset();
|
||||
_restaurantRunData.ReleaseAsset();
|
||||
_restaurantCustomerData.ReleaseAsset();
|
||||
var assetManager = AssetManager.Instance;
|
||||
if (!assetManager) return;
|
||||
|
||||
AssetManager.Instance.ReleaseAsset(_restaurantPlayerData);
|
||||
AssetManager.Instance.ReleaseAsset(_restaurantManagementData);
|
||||
AssetManager.Instance.ReleaseAsset(_restaurantRunData);
|
||||
AssetManager.Instance.ReleaseAsset(_restaurantCustomerData);
|
||||
|
||||
PlayerData = null;
|
||||
ManagementData = null;
|
||||
RunData = null;
|
||||
CustomerData = null;
|
||||
|
||||
_isLoaded = false;
|
||||
}
|
||||
|
@ -33,14 +33,14 @@ public async void Initialize(RestaurantPropLocation location)
|
||||
_renderer = spriteRenderer;
|
||||
spriteRenderer.sprite = DataManager.Instance.GetSprite(environmentData.SpriteKey);
|
||||
spriteRenderer.sortingOrder = 5;
|
||||
Material material = await AssetManager.LoadAsset<Material>(DataConstants.BasePropSpriteMaterial);
|
||||
spriteRenderer.material = new Material(material);
|
||||
//Material material = await AssetManager.LoadAssetAsync<Material>(DataConstants.BasePropSpriteMaterial);
|
||||
//spriteRenderer.material = new Material(material);
|
||||
}
|
||||
else if (environmentData.RendererType == RendererType.Spine)
|
||||
{
|
||||
var skeletonAnimation = _visualLook.AddComponent<SkeletonAnimation>();
|
||||
var skeletonDataAsset = await AssetManager.LoadAsset<SkeletonDataAsset>(environmentData.SkeletonDataName);
|
||||
skeletonAnimation.skeletonDataAsset = skeletonDataAsset;
|
||||
//var skeletonDataAsset = await AssetManager.LoadAssetAsync<SkeletonDataAsset>(environmentData.SkeletonDataName);
|
||||
//skeletonAnimation.skeletonDataAsset = skeletonDataAsset;
|
||||
var spineController = transform.AddComponent<SpineController>();
|
||||
spineController.SetSkin(environmentData.SkinName);
|
||||
spineController.PlayAnimation(environmentData.DefaultAnimationName, true);
|
||||
|
@ -1,17 +1,15 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Opsive.BehaviorDesigner.Runtime;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
using UnityEngine.ResourceManagement.AsyncOperations;
|
||||
|
||||
namespace DDD
|
||||
{
|
||||
public class RestaurantCustomerState : ScriptableObject
|
||||
{
|
||||
private Dictionary<CustomerType, Subtree> _loadedSubtrees = new Dictionary<CustomerType, Subtree>();
|
||||
private Dictionary<CustomerType, AsyncOperationHandle<Subtree>> _subtreeHandles = new Dictionary<CustomerType, AsyncOperationHandle<Subtree>>();
|
||||
private Dictionary<CustomerType, Subtree> _loadedSubtrees = new();
|
||||
private Dictionary<CustomerType, AssetReference> _subtreeAssetReference = new();
|
||||
|
||||
public async Task LoadCustomerBehaviorData()
|
||||
{
|
||||
@ -40,14 +38,12 @@ public async Task LoadCustomerBehaviorData()
|
||||
|
||||
private async Task LoadSubtreeAsync(CustomerType customerType, AssetReference subtreeReference)
|
||||
{
|
||||
var handle = Addressables.LoadAssetAsync<Subtree>(subtreeReference);
|
||||
_subtreeHandles[customerType] = handle;
|
||||
var subtree = await AssetManager.Instance.LoadAssetAsync<Subtree>(subtreeReference);
|
||||
|
||||
await handle.Task;
|
||||
|
||||
if (handle.Result != null)
|
||||
if (subtree != null)
|
||||
{
|
||||
_loadedSubtrees[customerType] = handle.Result;
|
||||
_loadedSubtrees[customerType] = subtree;
|
||||
_subtreeAssetReference[customerType] = subtreeReference;
|
||||
Debug.Log($"[RestaurantCustomerState] Loaded subtree for {customerType}");
|
||||
}
|
||||
else
|
||||
@ -58,16 +54,13 @@ private async Task LoadSubtreeAsync(CustomerType customerType, AssetReference su
|
||||
|
||||
public void UnloadCustomerBehaviorData()
|
||||
{
|
||||
foreach (var handle in _subtreeHandles.Values)
|
||||
foreach (var assetReference in _subtreeAssetReference.Values)
|
||||
{
|
||||
if (handle.IsValid())
|
||||
{
|
||||
Addressables.Release(handle);
|
||||
}
|
||||
AssetManager.Instance.ReleaseAsset(assetReference);
|
||||
}
|
||||
|
||||
_loadedSubtrees.Clear();
|
||||
_subtreeHandles.Clear();
|
||||
_subtreeAssetReference.Clear();
|
||||
Debug.Log("[RestaurantCustomerState] Unloaded all customer behavior subtrees");
|
||||
}
|
||||
|
||||
|
@ -39,21 +39,16 @@ public static T Instance
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
// 이중 체크 락킹 패턴
|
||||
if (_instance != null)
|
||||
return _instance;
|
||||
|
||||
try
|
||||
{
|
||||
var key = ResolveAddressKey();
|
||||
var handle = Addressables.LoadAssetAsync<T>(key);
|
||||
|
||||
// 동기 로드: 메인 스레드에서 호출할 것을 권장합니다.
|
||||
var loaded = handle.WaitForCompletion();
|
||||
|
||||
if (handle.Status != AsyncOperationStatus.Succeeded || loaded == null)
|
||||
var loaded = AssetManager.Instance.LoadAsset<T>(key);
|
||||
if (loaded == null)
|
||||
{
|
||||
throw new InvalidOperationException($"Addressables 로드 실패: 타입='{typeof(T).Name}', key='{key}'");
|
||||
throw new InvalidOperationException($"AssetManager를 통한 로드 실패: 타입='{typeof(T).Name}', key='{key}'");
|
||||
}
|
||||
|
||||
_instance = loaded;
|
||||
@ -62,9 +57,9 @@ public static T Instance
|
||||
|
||||
return _instance;
|
||||
}
|
||||
catch (Exception)
|
||||
catch (Exception e)
|
||||
{
|
||||
throw;
|
||||
throw new Exception(e.Message, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user