using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Fantasy.Async;
using UnityEngine;
using UnityEngine.SceneManagement;
using Object = UnityEngine.Object;
namespace NBC.Asset
{
public static class Assets
{
private static GameObject _monoGameObject;
private static bool _isInitialize;
private static NTaskStatus _initializeTaskStatus = NTaskStatus.None;
private static string _initializeError = string.Empty;
public static InitializationTask Initialize()
{
if (_isInitialize)
throw new Exception($"Repeated initialization!");
return InitConfirm();
}
#region 资源清理
///
/// 清理所有缓存
///
public static void ClearAllCache()
{
if (Directory.Exists(Const.SavePath))
{
Directory.Delete(Const.SavePath, true);
}
}
#endregion
#region 资源加载
public static T Load(string path) where T : Object
{
var assetProvider = LoadAsset(path, typeof(T));
if (assetProvider != null)
{
return assetProvider.Asset as T;
}
return default(T);
}
public static async FTask LoadAsync(string path) where T : Object
{
var assetProvider = LoadAssetAsync(path, typeof(T));
await assetProvider.Task;
if (assetProvider.Asset != null)
{
return assetProvider.Asset as T;
}
return null;
}
public static AssetProvider LoadAsset(string path)
{
return LoadAsset(path, typeof(T));
}
public static AssetProvider LoadAsset(string path, Type type)
{
var req = LoadAssetAsync(path, type);
req?.WaitForAsyncComplete();
return req;
}
public static AssetProvider LoadAssetAsync(string path)
{
return LoadAssetAsync(path, typeof(T));
}
public static AssetProvider LoadAssetAsync(string path, Type type)
{
var assetInfo = Addressable.GetAssetInfo(path, type);
return AssetProvider.GetAssetProvider(assetInfo);
}
public static AssetProvider LoadAssetAll(string path)
{
return LoadAssetAll(path, typeof(T));
}
public static AssetProvider LoadAssetAll(string path, Type type)
{
var req = LoadAssetAllAsync(path, type);
req?.WaitForAsyncComplete();
return req;
}
public static AssetProvider LoadAssetAllAsync(string path)
{
return LoadAssetAllAsync(path, typeof(T));
}
public static AssetProvider LoadAssetAllAsync(string path, Type type)
{
var assetInfo = Addressable.GetAssetInfo(path, type);
return AssetProvider.GetAssetProvider(assetInfo, true);
}
#endregion
#region 场景加载
public static SceneProvider LoadScene(string path, bool additive = false)
{
var assetInfo = Addressable.GetAssetInfo(path, typeof(Scene));
if (assetInfo == null)
{
throw new Exception($"Scene is null,path={path}");
}
return SceneProvider.GetSceneProvider(assetInfo, additive);
}
#endregion
#region 资源卸载
///
/// 释放所有资源
///
/// 强制释放
public static void ReleaseAllAssets(bool force = true)
{
AssetProvider.ReleaseAllAssets(force);
SceneProvider.ReleaseAllAssets(force);
}
///
/// 根据标签,释放所有资源
///
/// 标签
/// 强制释放
public static void ReleaseAllAssetsByTag(string[] tags, bool force = true)
{
AssetProvider.ReleaseAllAssetsByTag(tags, force);
SceneProvider.ReleaseAllAssetsByTag(tags, force);
}
#endregion
#region 检查解压
///
/// 可以解压的bundle包数量
///
///
public static int CanUnpackBundleCount()
{
var arr = Addressable.GetCanUnpackBundles();
return arr != null ? arr.Length : 0;
}
///
/// 解压资源包任务(解压本地存在的所有资源)
///
/// 自动运行
///
public static UnpackPackagesTask CreateUnpackPackagesTask(bool run = true)
{
var task = new UnpackPackagesTask();
if (run) task.Run(TaskRunner.Def);
return task;
}
#endregion
#region 检查更新
///
/// 获取当前版本可以下载到本地的bundle包
///
///
public static List GetCanDownloadBundles()
{
List ret = new List();
var bundles = Addressable.GetCanDownloadBundles();
foreach (var bundleInfo in bundles)
{
var bundleData = bundleInfo.Bundle;
//可优化。缓存所有packageName,但该逻辑理论全局只会调用一次,是否需要缓存值得考虑
if (bundleData != null && IsNeedfulPackage(bundleData.PackageName))
{
ret.Add(bundleInfo);
}
}
return ret;
}
///
/// 主动下载需要的bundles包任务
///
/// 需要下载的bundle
/// 自动运行
///
public static DownloadBundlesTask CreateDownloadBundlesTask(List downloadBundles, bool run = true)
{
var task = new DownloadBundlesTask(downloadBundles);
if (run) task.Run();
return task;
}
///
/// 创建检查更新任务
///
///
public static CheckUpdateTask CreateCheckUpdateTask(bool run = true)
{
var task = new CheckUpdateTask();
if (run) task.Run(TaskRunner.Def);
return task;
}
///
/// 创建版本更新任务
///
public static UpdateVersionTask CreateUpdateVersionTask(UpdateContext context, bool run = true)
{
var task = new UpdateVersionTask(context);
if (run) task.Run();
return task;
}
#endregion
#region 默认资源包
private static readonly HashSet _defaultPackage = new HashSet();
///
/// 添加一个包进入需要列表
///
///
public static void AddNeedfulPackage(string packageName)
{
_defaultPackage.Add(packageName);
}
///
/// 移除一个需要的资源包
///
///
public static void RemoveNeedfulPackage(string packageName)
{
if (_defaultPackage.Contains(packageName)) _defaultPackage.Remove(packageName);
}
///
/// 移除全部额外需要包
///
public static void RemoveAllNeedful()
{
_defaultPackage.Clear();
}
///
/// 是否需要这个资源包
///
///
///
public static bool IsNeedfulPackage(string packageName)
{
var ret = _defaultPackage.Contains(packageName);
if (!ret)
{
var package = Addressable.GetPackageData(packageName);
if (package != null)
{
return package.Def == 1;
}
}
return ret;
}
#endregion
#region 调试
#if DEBUG
private static DebugRemoteServer _debugRemoteServer;
public static void StartDebugRemoteServer()
{
_debugRemoteServer = _monoGameObject.AddComponent();
}
public static void StopDebugRemoteServer()
{
if (_debugRemoteServer != null)
{
Object.DestroyImmediate(_debugRemoteServer);
}
}
public static DebugInfo GetDebugInfos()
{
DebugInfo info = new DebugInfo();
info.Frame = Time.frameCount;
var assetProviders = AssetProvider.GetAssetProviders();
foreach (var asset in assetProviders)
{
var i = CreateDebugAssetInfo(asset.AssetInfo, asset.IsAll);
SetDebugBaseInfo(asset, i);
info.AssetInfos.Add(i);
}
var sceneProviders = SceneProvider.GetSceneProviders();
foreach (var scene in sceneProviders)
{
var i = CreateDebugAssetInfo(scene.AssetInfo, false);
SetDebugBaseInfo(scene, i);
info.AssetInfos.Add(i);
}
var bundleProviders = BundledProvider.GetBundleProviders();
foreach (var bundle in bundleProviders)
{
var bundleInfo = new DebugBundleInfo
{
BundleName = bundle.BundleInfo.Bundle.Name
};
SetDebugBaseInfo(bundle, bundleInfo);
info.BundleInfos.Add(bundleInfo);
}
return info;
}
private static DebugAssetInfo CreateDebugAssetInfo(AssetInfo asset, bool isAll)
{
var assetInfo = new DebugAssetInfo
{
Path = asset.Path,
Type = asset.AssetType.Name,
IsAll = isAll,
};
var bundleInfos = Addressable.GetAllDependBundleInfos(asset);
foreach (var bundle in bundleInfos)
{
assetInfo.Dependency.Add(bundle.Bundle.Name);
}
return assetInfo;
}
private static void SetDebugBaseInfo(ProviderBase provider, DebugBaseInfo info)
{
info.LoadScene = provider.LoadScene;
info.Ref = provider.RefCount;
info.Status = provider.Status.ToString();
info.LoadTime = provider.LoadTime;
info.LoadTotalTime = provider.LoadTotalTime;
}
#endif
#endregion
#region Private
private static void Update()
{
TaskRunner.Update();
Recycler.Update();
}
private static InitializationTask InitConfirm()
{
_monoGameObject = new GameObject("Assets", typeof(Mono));
Mono.AddUpdate(Update);
InitializationTask task;
#if UNITY_STANDALONE_WIN
Const.NotCache = true;
#endif
if (Const.Simulate)
{
task = new EditorInitializationTask();
AssetProvider.CreateLoader = AssetLoadFromDatabase.CreateInstance;
SceneProvider.CreateLoader = SceneLoadFromDatabase.CreateInstance;
}
else if (Const.Offline)
{
task = new OfflineInitializationTask();
}
else
{
task = new OnlineInitializationTask();
}
if (Const.IsWebGLPlatform)
{
Const.RemoteUrl = $"{Application.streamingAssetsPath}/";
}
task.OnCompleted(InitDone);
task.Run(TaskRunner.Def);
_isInitialize = true;
return task;
}
///
/// 初始化完成回调
///
///
private static void InitDone(ITask taskBase)
{
Debug.Log("初始化完成===");
_initializeTaskStatus = taskBase.Status;
_initializeError = taskBase.ErrorMsg;
}
#endregion
}
}