using System.Threading; using AlicizaX.Resource.Runtime; using Cysharp.Threading.Tasks; using UnityEngine; namespace AlicizaX { public interface IResourceLoader { GameObject LoadPrefab(string location); UniTask LoadPrefabAsync(string location, CancellationToken cancellationToken = default); GameObject LoadGameObject(string location, Transform parent = null); UniTask LoadGameObjectAsync(string location, Transform parent = null, CancellationToken cancellationToken = default); void UnloadAsset(GameObject gameObject); } public class UnityResourcesLoader : IResourceLoader { private static bool AllowLegacyResourcesFallback => Application.isEditor || Debug.isDebugBuild; public GameObject LoadPrefab(string location) { if (TryGetResourceService(out var resourceService)) { var prefab = resourceService.LoadAsset(location); if (prefab != null) { return prefab; } } return AllowLegacyResourcesFallback ? Resources.Load(location) : null; } public async UniTask LoadPrefabAsync(string location, CancellationToken cancellationToken = default) { if (TryGetResourceService(out var resourceService)) { var prefab = await resourceService.LoadAssetAsync(location, cancellationToken); if (prefab != null) { return prefab; } } return AllowLegacyResourcesFallback ? await Resources.LoadAsync(location).ToUniTask(cancellationToken: cancellationToken) as GameObject : null; } public GameObject LoadGameObject(string location, Transform parent = null) { if (TryGetResourceService(out var resourceService)) { var managedObject = resourceService.LoadGameObject(location, parent); if (managedObject != null) { return managedObject; } } if (!AllowLegacyResourcesFallback) return null; var prefab = Resources.Load(location); if (prefab == null) return null; var instance = GameObject.Instantiate(prefab); if (instance != null && parent != null) { instance.transform.SetParent(parent); } return instance; } public async UniTask LoadGameObjectAsync(string location, Transform parent = null, CancellationToken cancellationToken = default) { if (TryGetResourceService(out var resourceService)) { var managedObject = await resourceService.LoadGameObjectAsync(location, parent, cancellationToken); if (managedObject != null) { return managedObject; } } if (!AllowLegacyResourcesFallback) return null; var prefab = await Resources.LoadAsync(location).ToUniTask(cancellationToken: cancellationToken) as GameObject; if (prefab == null) return null; var instance = GameObject.Instantiate(prefab); if (instance != null && parent != null) { instance.transform.SetParent(parent); } return instance; } public void UnloadAsset(GameObject gameObject) { // Resources.UnloadAsset cannot unload GameObjects. // The prefab reference is nulled by the caller; Unity handles cleanup via UnloadUnusedAssets. } private static bool TryGetResourceService(out IResourceService resourceService) { return AppServices.TryGet(out resourceService); } } public class AssetBundleResourceLoader : IResourceLoader { private IResourceService _resourceService; IResourceService ResourceService { get { if (_resourceService == null) { _resourceService = AppServices.Require(); } return _resourceService; } } public GameObject LoadPrefab(string location) { return ResourceService.LoadAsset(location); } public async UniTask LoadPrefabAsync(string location, CancellationToken cancellationToken = default) { return await ResourceService.LoadAssetAsync(location, cancellationToken); } public GameObject LoadGameObject(string location, Transform parent = null) { return ResourceService.LoadGameObject(location, parent); } public async UniTask LoadGameObjectAsync(string location, Transform parent = null, CancellationToken cancellationToken = default) { return await ResourceService.LoadGameObjectAsync(location, parent, cancellationToken); } public void UnloadAsset(GameObject gameObject) { ResourceService.UnloadAsset(gameObject); } } }