YooAsset/Assets/YooAsset/Runtime/YooAssets.cs

552 lines
16 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.Collections;
using System.Collections.Generic;
namespace YooAsset
{
public static class YooAssets
{
/// <summary>
/// 运行模式
/// </summary>
private enum EPlayMode
{
/// <summary>
/// 编辑器下模拟运行模式
/// </summary>
EditorPlayMode,
/// <summary>
/// 离线模式
/// </summary>
OfflinePlayMode,
/// <summary>
/// 网络模式
/// </summary>
HostPlayMode,
}
public abstract class CreateParameters
{
/// <summary>
/// 资源定位的根路径
/// 例如Assets/MyResource
/// </summary>
public string LocationRoot;
/// <summary>
/// 文件解密接口
/// </summary>
public IDecryptServices DecryptServices = null;
/// <summary>
/// 资源系统自动释放零引用资源的间隔秒数
/// 注意如果小于等于零代表不自动释放可以使用YooAssets.UnloadUnusedAssets接口主动释放
/// </summary>
public float AutoReleaseInterval = -1;
/// <summary>
/// 资源加载的最大数量
/// </summary>
public int AssetLoadingMaxNumber = int.MaxValue;
}
/// <summary>
/// 编辑器下模拟运行(只支持在编辑器下运行)
/// </summary>
public class EditorPlayModeParameters : CreateParameters
{
}
/// <summary>
/// 离线模式(本地打包运行模式)
/// </summary>
public class OfflinePlayModeParameters : CreateParameters
{
}
/// <summary>
/// 网络模式(网络打包运行模式)
/// </summary>
public class HostPlayModeParameters : CreateParameters
{
/// <summary>
/// 当缓存池被污染的时候清理缓存池
/// </summary>
public bool ClearCacheWhenDirty;
/// <summary>
/// 忽略资源版本号
/// </summary>
public bool IgnoreResourceVersion;
/// <summary>
/// 默认的资源服务器下载地址
/// </summary>
public string DefaultHostServer;
/// <summary>
/// 备用的资源服务器下载地址
/// </summary>
public string FallbackHostServer;
}
private static bool _isInitialize = false;
private static string _locationRoot;
private static EPlayMode _playMode;
private static IBundleServices _bundleServices;
private static EditorPlayModeImpl _editorPlayModeImpl;
private static OfflinePlayModeImpl _offlinePlayModeImpl;
private static HostPlayModeImpl _hostPlayModeImpl;
private static float _releaseTimer;
private static float _releaseCD = -1f;
/// <summary>
/// 异步初始化
/// </summary>
public static InitializationOperation InitializeAsync(CreateParameters parameters)
{
if (parameters == null)
throw new Exception($"YooAsset create parameters is invalid.");
#if !UNITY_EDITOR
if (parameters is EditorPlayModeParameters)
throw new Exception($"Editor play mode only support unity editor.");
#endif
// 创建驱动器
if (_isInitialize == false)
{
_isInitialize = true;
UnityEngine.GameObject driver = new UnityEngine.GameObject("[YooAsset]");
var driverGo = driver.AddComponent<YooAssetDriver>().gameObject;
UnityEngine.Object.DontDestroyOnLoad(driverGo);
}
else
{
throw new Exception("YooAsset is initialized yet.");
}
// 检测创建参数
if (parameters.AssetLoadingMaxNumber < 3)
{
parameters.AssetLoadingMaxNumber = 3;
Logger.Warning($"{nameof(parameters.AssetLoadingMaxNumber)} minimum is 3");
}
// 创建间隔计时器
if (parameters.AutoReleaseInterval > 0)
{
_releaseCD = parameters.AutoReleaseInterval;
}
if (string.IsNullOrEmpty(parameters.LocationRoot) == false)
_locationRoot = AssetPathHelper.GetRegularPath(parameters.LocationRoot);
// 运行模式
if (parameters is EditorPlayModeParameters)
_playMode = EPlayMode.EditorPlayMode;
else if (parameters is OfflinePlayModeParameters)
_playMode = EPlayMode.OfflinePlayMode;
else if (parameters is HostPlayModeParameters)
_playMode = EPlayMode.HostPlayMode;
else
throw new NotImplementedException();
// 初始化
if (_playMode == EPlayMode.EditorPlayMode)
{
_editorPlayModeImpl = new EditorPlayModeImpl();
_bundleServices = _editorPlayModeImpl;
AssetSystem.Initialize(true, parameters.AssetLoadingMaxNumber, parameters.DecryptServices, _bundleServices);
return _editorPlayModeImpl.InitializeAsync();
}
else if (_playMode == EPlayMode.OfflinePlayMode)
{
_offlinePlayModeImpl = new OfflinePlayModeImpl();
_bundleServices = _offlinePlayModeImpl;
AssetSystem.Initialize(false, parameters.AssetLoadingMaxNumber, parameters.DecryptServices, _bundleServices);
return _offlinePlayModeImpl.InitializeAsync();
}
else if (_playMode == EPlayMode.HostPlayMode)
{
_hostPlayModeImpl = new HostPlayModeImpl();
_bundleServices = _hostPlayModeImpl;
AssetSystem.Initialize(false, parameters.AssetLoadingMaxNumber, parameters.DecryptServices, _bundleServices);
var hostPlayModeParameters = parameters as HostPlayModeParameters;
return _hostPlayModeImpl.InitializeAsync(
hostPlayModeParameters.ClearCacheWhenDirty,
hostPlayModeParameters.IgnoreResourceVersion,
hostPlayModeParameters.DefaultHostServer,
hostPlayModeParameters.FallbackHostServer);
}
else
{
throw new NotImplementedException();
}
}
/// <summary>
/// 向网络端请求并更新补丁清单
/// </summary>
/// <param name="updateResourceVersion">更新的资源版本号</param>
/// <param name="timeout">超时时间</param>
public static UpdateManifestOperation UpdateManifestAsync(int updateResourceVersion, int timeout)
{
if (_playMode == EPlayMode.EditorPlayMode)
{
var operation = new EditorModeUpdateManifestOperation();
OperationUpdater.ProcessOperaiton(operation);
return operation;
}
else if (_playMode == EPlayMode.OfflinePlayMode)
{
var operation = new OfflinePlayModeUpdateManifestOperation();
OperationUpdater.ProcessOperaiton(operation);
return operation;
}
else if (_playMode == EPlayMode.HostPlayMode)
{
if (_hostPlayModeImpl == null)
throw new Exception("YooAsset is not initialized.");
return _hostPlayModeImpl.UpdatePatchManifestAsync(updateResourceVersion, timeout);
}
else
{
throw new NotImplementedException();
}
}
/// <summary>
/// 更新资源系统
/// </summary>
internal static void InternalUpdate()
{
// 更新异步请求操作
OperationUpdater.Update();
// 更新下载管理系统
DownloadSystem.Update();
// 轮询更新资源系统
AssetSystem.Update();
// 自动释放零引用资源
if (_releaseCD > 0)
{
_releaseTimer += UnityEngine.Time.unscaledDeltaTime;
if (_releaseTimer >= _releaseCD)
{
_releaseTimer = 0f;
AssetSystem.UnloadUnusedAssets();
}
}
}
/// <summary>
/// 获取资源版本号
/// </summary>
public static int GetResourceVersion()
{
if (_playMode == EPlayMode.EditorPlayMode)
{
if (_editorPlayModeImpl == null)
throw new Exception("YooAsset is not initialized.");
return _editorPlayModeImpl.GetResourceVersion();
}
else if (_playMode == EPlayMode.OfflinePlayMode)
{
if (_offlinePlayModeImpl == null)
throw new Exception("YooAsset is not initialized.");
return _offlinePlayModeImpl.GetResourceVersion();
}
else if (_playMode == EPlayMode.HostPlayMode)
{
if (_hostPlayModeImpl == null)
throw new Exception("YooAsset is not initialized.");
return _hostPlayModeImpl.GetResourceVersion();
}
else
{
throw new NotImplementedException();
}
}
/// <summary>
/// 获取内置资源标记列表
/// </summary>
public static string[] GetManifestBuildinTags()
{
if (_playMode == EPlayMode.EditorPlayMode)
{
if (_editorPlayModeImpl == null)
throw new Exception("YooAsset is not initialized.");
return _editorPlayModeImpl.GetManifestBuildinTags();
}
else if (_playMode == EPlayMode.OfflinePlayMode)
{
if (_offlinePlayModeImpl == null)
throw new Exception("YooAsset is not initialized.");
return _offlinePlayModeImpl.GetManifestBuildinTags();
}
else if (_playMode == EPlayMode.HostPlayMode)
{
if (_hostPlayModeImpl == null)
throw new Exception("YooAsset is not initialized.");
return _hostPlayModeImpl.GetManifestBuildinTags();
}
else
{
throw new NotImplementedException();
}
}
/// <summary>
/// 获取资源包信息
/// </summary>
public static AssetBundleInfo GetAssetBundleInfo(string location)
{
string assetPath = ConvertLocationToAssetPath(location);
string bundleName = _bundleServices.GetAssetBundleName(assetPath);
return _bundleServices.GetAssetBundleInfo(bundleName);
}
/// <summary>
/// 资源回收(卸载引用计数为零的资源)
/// </summary>
public static void UnloadUnusedAssets()
{
AssetSystem.Update();
AssetSystem.UnloadUnusedAssets();
}
/// <summary>
/// 强制回收所有资源
/// </summary>
public static void ForceUnloadAllAssets()
{
AssetSystem.ForceUnloadAllAssets();
}
/// <summary>
/// 获取调试汇总信息
/// </summary>
public static void GetDebugSummy(DebugSummy summy)
{
if (summy == null)
Logger.Error($"{nameof(DebugSummy)} is null");
AssetSystem.GetDebugSummy(summy);
}
#region 资源加载接口
/// <summary>
/// 同步加载资源对象
/// </summary>
/// <param name="location">资源对象相对路径</param>
public static AssetOperationHandle LoadAssetSync<TObject>(string location) where TObject : class
{
return LoadAssetInternal(location, typeof(TObject), true);
}
public static AssetOperationHandle LoadAssetSync(System.Type type, string location)
{
return LoadAssetInternal(location, type, true);
}
/// <summary>
/// 同步加载子资源对象集合
/// </summary>
/// <param name="location">资源对象相对路径</param>
public static AssetOperationHandle LoadSubAssetsSync<TObject>(string location)
{
return LoadSubAssetsInternal(location, typeof(TObject), true);
}
public static AssetOperationHandle LoadSubAssetsSync(System.Type type, string location)
{
return LoadSubAssetsInternal(location, type, true);
}
/// <summary>
/// 异步加载场景
/// </summary>
public static AssetOperationHandle LoadSceneAsync(string location, SceneInstanceParam instanceParam)
{
string scenePath = ConvertLocationToAssetPath(location);
var handle = AssetSystem.LoadSceneAsync(scenePath, instanceParam);
return handle;
}
/// <summary>
/// 异步加载资源对象
/// </summary>
/// <param name="location">资源对象相对路径</param>
public static AssetOperationHandle LoadAssetAsync<TObject>(string location)
{
return LoadAssetInternal(location, typeof(TObject), false);
}
public static AssetOperationHandle LoadAssetAsync(System.Type type, string location)
{
return LoadAssetInternal(location, type, false);
}
/// <summary>
/// 异步加载子资源对象集合
/// </summary>
/// <param name="location">资源对象相对路径</param>
public static AssetOperationHandle LoadSubAssetsAsync<TObject>(string location)
{
return LoadSubAssetsInternal(location, typeof(TObject), false);
}
public static AssetOperationHandle LoadSubAssetsAsync(System.Type type, string location)
{
return LoadSubAssetsInternal(location, type, false);
}
private static AssetOperationHandle LoadAssetInternal(string location, System.Type assetType, bool waitForAsyncComplete)
{
string assetPath = ConvertLocationToAssetPath(location);
var handle = AssetSystem.LoadAssetAsync(assetPath, assetType);
if (waitForAsyncComplete)
handle.WaitForAsyncComplete();
return handle;
}
private static AssetOperationHandle LoadSubAssetsInternal(string location, System.Type assetType, bool waitForAsyncComplete)
{
string assetPath = ConvertLocationToAssetPath(location);
var handle = AssetSystem.LoadSubAssetsAsync(assetPath, assetType);
if (waitForAsyncComplete)
handle.WaitForAsyncComplete();
return handle;
}
#endregion
#region 资源下载接口
/// <summary>
/// 创建补丁下载器
/// </summary>
/// <param name="tag">资源标签</param>
/// <param name="downloadingMaxNumber">同时下载的最大文件数</param>
/// <param name="failedTryAgain">下载失败的重试次数</param>
public static DownloaderOperation CreatePatchDownloader(string tag, int downloadingMaxNumber, int failedTryAgain)
{
return CreatePatchDownloader(new string[] { tag }, downloadingMaxNumber, failedTryAgain);
}
/// <summary>
/// 创建补丁下载器
/// </summary>
/// <param name="tags">资源标签列表</param>
/// <param name="downloadingMaxNumber">同时下载的最大文件数</param>
/// <param name="failedTryAgain">下载失败的重试次数</param>
public static DownloaderOperation CreatePatchDownloader(string[] tags, int downloadingMaxNumber, int failedTryAgain)
{
if (_playMode == EPlayMode.EditorPlayMode)
{
List<AssetBundleInfo> downloadList = new List<AssetBundleInfo>();
var operation = new DownloaderOperation(downloadList, downloadingMaxNumber, failedTryAgain);
return operation;
}
else if (_playMode == EPlayMode.OfflinePlayMode)
{
List<AssetBundleInfo> downloadList = new List<AssetBundleInfo>();
var operation = new DownloaderOperation(downloadList, downloadingMaxNumber, failedTryAgain);
return operation;
}
else if (_playMode == EPlayMode.HostPlayMode)
{
if (_hostPlayModeImpl == null)
throw new Exception("YooAsset is not initialized.");
return _hostPlayModeImpl.CreateDownloaderByTags(tags, downloadingMaxNumber, failedTryAgain);
}
else
{
throw new NotImplementedException();
}
}
/// <summary>
/// 创建资源包下载器
/// </summary>
/// <param name="locations">资源列表</param>
/// <param name="downloadingMaxNumber">同时下载的最大文件数</param>
/// <param name="failedTryAgain">下载失败的重试次数</param>
public static DownloaderOperation CreateBundleDownloader(string[] locations, int downloadingMaxNumber, int failedTryAgain)
{
if (_playMode == EPlayMode.EditorPlayMode)
{
List<AssetBundleInfo> downloadList = new List<AssetBundleInfo>();
var operation = new DownloaderOperation(downloadList, downloadingMaxNumber, failedTryAgain);
return operation;
}
else if (_playMode == EPlayMode.OfflinePlayMode)
{
List<AssetBundleInfo> downloadList = new List<AssetBundleInfo>();
var operation = new DownloaderOperation(downloadList, downloadingMaxNumber, failedTryAgain);
return operation;
}
else if (_playMode == EPlayMode.HostPlayMode)
{
if (_hostPlayModeImpl == null)
throw new Exception("YooAsset is not initialized.");
List<string> assetPaths = new List<string>(locations.Length);
foreach (var location in locations)
{
string assetPath = ConvertLocationToAssetPath(location);
assetPaths.Add(assetPath);
}
return _hostPlayModeImpl.CreateDownloaderByPaths(assetPaths, downloadingMaxNumber, failedTryAgain);
}
else
{
throw new NotImplementedException();
}
}
#endregion
#region 沙盒相关
/// <summary>
/// 清空沙盒目录
/// 注意:可以使用该方法修复我们本地的客户端
/// </summary>
public static void ClearSandbox()
{
Logger.Warning("Clear sandbox.");
PatchHelper.ClearSandbox();
}
/// <summary>
/// 获取沙盒文件夹的路径
/// </summary>
public static string GetSandboxRoot()
{
return AssetPathHelper.MakePersistentRootPath();
}
#endregion
#region 内部方法
/// <summary>
/// 定位地址转换为资源路径
/// </summary>
private static string ConvertLocationToAssetPath(string location)
{
if (_playMode == EPlayMode.EditorPlayMode)
{
string filePath = AssetPathHelper.CombineAssetPath(_locationRoot, location);
return AssetPathHelper.FindDatabaseAssetPath(filePath);
}
else
{
return AssetPathHelper.CombineAssetPath(_locationRoot, location);
}
}
#endregion
}
}