diff --git a/Assets/YooAsset/Runtime/InitializeParameters.cs b/Assets/YooAsset/Runtime/InitializeParameters.cs new file mode 100644 index 0000000..961df17 --- /dev/null +++ b/Assets/YooAsset/Runtime/InitializeParameters.cs @@ -0,0 +1,96 @@ +using UnityEngine; + +namespace YooAsset +{ + /// + /// 初始化参数 + /// + public abstract class InitializeParameters + { + /// + /// 资源定位地址大小写不敏感 + /// + public bool LocationToLower = false; + + /// + /// 资源定位服务接口 + /// + public ILocationServices LocationServices = null; + + /// + /// 文件解密服务接口 + /// + public IDecryptionServices DecryptionServices = null; + + /// + /// 资源加载的最大数量 + /// + public int AssetLoadingMaxNumber = int.MaxValue; + + /// + /// 异步操作系统每帧允许运行的最大时间切片(单位:毫秒) + /// + public long OperationSystemMaxTimeSlice = long.MaxValue; + } + + /// + /// 编辑器下模拟运行模式的初始化参数 + /// + public class EditorSimulateModeParameters : InitializeParameters + { + /// + /// 用于模拟运行的资源清单路径 + /// 注意:如果路径为空,会自动重新构建补丁清单。 + /// + public string SimulatePatchManifestPath; + } + + /// + /// 离线运行模式的初始化参数 + /// + public class OfflinePlayModeParameters : InitializeParameters + { + /// + /// 内置的资源包裹名称 + /// + public string BuildinPackageName = string.Empty; + } + + /// + /// 联机运行模式的初始化参数 + /// + public class HostPlayModeParameters : InitializeParameters + { + /// + /// 默认的资源服务器下载地址 + /// + public string DefaultHostServer; + + /// + /// 备用的资源服务器下载地址 + /// + public string FallbackHostServer; + +#if UNITY_WEBGL + /// + /// WEBGL模式不支持多线程下载 + /// + internal int BreakpointResumeFileSize = int.MaxValue; +#else + /// + /// 启用断点续传功能的文件大小 + /// + public int BreakpointResumeFileSize = int.MaxValue; +#endif + + /// + /// 下载文件校验等级 + /// + public EVerifyLevel VerifyLevel = EVerifyLevel.High; + + /// + /// 查询服务类 + /// + public IQueryServices QueryServices = null; + } +} \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/InitializeParameters.cs.meta b/Assets/YooAsset/Runtime/InitializeParameters.cs.meta new file mode 100644 index 0000000..792e109 --- /dev/null +++ b/Assets/YooAsset/Runtime/InitializeParameters.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a9b5e8a77215adb45b203be8a4fb9eda +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/YooAsset/Runtime/YooAssetComponent.cs b/Assets/YooAsset/Runtime/YooAssetComponent.cs new file mode 100644 index 0000000..bb14bf3 --- /dev/null +++ b/Assets/YooAsset/Runtime/YooAssetComponent.cs @@ -0,0 +1,1087 @@ +using System; +using System.Diagnostics; +using System.Collections; +using System.Collections.Generic; +using UnityEngine.SceneManagement; + +namespace YooAsset +{ + public class YooAssetComponent + { + /// + /// 运行模式 + /// + public enum EPlayMode + { + /// + /// 编辑器下的模拟模式 + /// 注意:在初始化的时候自动构建真机模拟环境。 + /// + EditorSimulateMode, + + /// + /// 离线运行模式 + /// + OfflinePlayMode, + + /// + /// 联机运行模式 + /// + HostPlayMode, + } + + private bool _isInitialize = false; + private string _initializeError = string.Empty; + private EOperationStatus _initializeStatus = EOperationStatus.None; + private EPlayMode _playMode; + private IBundleServices _bundleServices; + private ILocationServices _locationServices; + private EditorSimulateModeImpl _editorSimulateModeImpl; + private OfflinePlayModeImpl _offlinePlayModeImpl; + private HostPlayModeImpl _hostPlayModeImpl; + + + /// + /// 是否已经初始化 + /// + public bool IsInitialized + { + get { return _isInitialize; } + } + + /// + /// 异步初始化 + /// + public InitializationOperation InitializeAsync(InitializeParameters parameters) + { + if (parameters == null) + throw new Exception($"YooAsset create parameters is null."); + +#if !UNITY_EDITOR + if (parameters is EditorSimulateModeParameters) + throw new Exception($"Editor simulate mode only support unity editor."); +#endif + + // 鉴定运行模式 + if (parameters is EditorSimulateModeParameters) + _playMode = EPlayMode.EditorSimulateMode; + else if (parameters is OfflinePlayModeParameters) + _playMode = EPlayMode.OfflinePlayMode; + else if (parameters is HostPlayModeParameters) + _playMode = EPlayMode.HostPlayMode; + else + throw new NotImplementedException(); + + if (parameters.LocationServices == null) + throw new Exception($"{nameof(IBundleServices)} is null."); + + if (_playMode == EPlayMode.OfflinePlayMode) + { + var playModeParameters = parameters as OfflinePlayModeParameters; + if (string.IsNullOrEmpty(playModeParameters.BuildinPackageName)) + throw new Exception($"{nameof(playModeParameters.BuildinPackageName)} is empty."); + } + + if (_playMode == EPlayMode.HostPlayMode) + { + var playModeParameters = parameters as HostPlayModeParameters; + if (playModeParameters.QueryServices == null) + throw new Exception($"{nameof(IQueryServices)} is null."); + } + + if (_isInitialize) + { + throw new Exception("YooAsset is initialized yet."); + } + + _locationServices = parameters.LocationServices; + + // 检测参数范围 + if (parameters.AssetLoadingMaxNumber < 1) + { + parameters.AssetLoadingMaxNumber = 1; + YooLogger.Warning($"{nameof(parameters.AssetLoadingMaxNumber)} minimum value is 1"); + } + if (parameters.OperationSystemMaxTimeSlice < 30) + { + parameters.OperationSystemMaxTimeSlice = 30; + YooLogger.Warning($"{nameof(parameters.OperationSystemMaxTimeSlice)} minimum value is 30 milliseconds"); + } + + // 创建驱动器 + if (_isInitialize == false) + { + _isInitialize = true; + UnityEngine.GameObject driverGo = new UnityEngine.GameObject("[YooAsset]"); + driverGo.AddComponent(); + UnityEngine.Object.DontDestroyOnLoad(driverGo); + +#if DEBUG + driverGo.AddComponent(); +#endif + } + + // 初始化异步系统 + OperationSystem.Initialize(parameters.OperationSystemMaxTimeSlice); + + // 初始化下载系统 + if (_playMode == EPlayMode.HostPlayMode) + { + var hostPlayModeParameters = parameters as HostPlayModeParameters; + CacheSystem.Initialize(hostPlayModeParameters.VerifyLevel); + DownloadSystem.Initialize(hostPlayModeParameters.BreakpointResumeFileSize); + } + else + { + CacheSystem.Initialize(EVerifyLevel.Low); + DownloadSystem.Initialize(int.MaxValue); + } + + // 初始化资源系统 + InitializationOperation initializeOperation; + if (_playMode == EPlayMode.EditorSimulateMode) + { + _editorSimulateModeImpl = new EditorSimulateModeImpl(); + _bundleServices = _editorSimulateModeImpl; + AssetSystem.Initialize(true, parameters.AssetLoadingMaxNumber, parameters.DecryptionServices, _bundleServices); + var simulateModeParameters = parameters as EditorSimulateModeParameters; + initializeOperation = _editorSimulateModeImpl.InitializeAsync( + simulateModeParameters.LocationToLower, + simulateModeParameters.SimulatePatchManifestPath); + } + else if (_playMode == EPlayMode.OfflinePlayMode) + { + _offlinePlayModeImpl = new OfflinePlayModeImpl(); + _bundleServices = _offlinePlayModeImpl; + AssetSystem.Initialize(false, parameters.AssetLoadingMaxNumber, parameters.DecryptionServices, _bundleServices); + var playModeParameters = parameters as OfflinePlayModeParameters; + initializeOperation = _offlinePlayModeImpl.InitializeAsync( + playModeParameters.LocationToLower, + playModeParameters.BuildinPackageName); + } + else if (_playMode == EPlayMode.HostPlayMode) + { + _hostPlayModeImpl = new HostPlayModeImpl(); + _bundleServices = _hostPlayModeImpl; + AssetSystem.Initialize(false, parameters.AssetLoadingMaxNumber, parameters.DecryptionServices, _bundleServices); + var playModeParameters = parameters as HostPlayModeParameters; + initializeOperation = _hostPlayModeImpl.InitializeAsync( + playModeParameters.LocationToLower, + playModeParameters.DefaultHostServer, + playModeParameters.FallbackHostServer, + playModeParameters.QueryServices); + } + else + { + throw new NotImplementedException(); + } + + // 监听初始化结果 + initializeOperation.Completed += InitializeOperation_Completed; + return initializeOperation; + } + private void InitializeOperation_Completed(AsyncOperationBase op) + { + _initializeStatus = op.Status; + _initializeError = op.Error; + } + + /// + /// 向网络端请求静态资源版本 + /// + /// 更新的资源包裹名称 + /// 超时时间(默认值:60秒) + public UpdateStaticVersionOperation UpdateStaticVersionAsync(string packageName, int timeout = 60) + { + DebugCheckInitialize(); + if (_playMode == EPlayMode.EditorSimulateMode) + { + var operation = new EditorPlayModeUpdateStaticVersionOperation(); + OperationSystem.StartOperation(operation); + return operation; + } + else if (_playMode == EPlayMode.OfflinePlayMode) + { + var operation = new OfflinePlayModeUpdateStaticVersionOperation(); + OperationSystem.StartOperation(operation); + return operation; + } + else if (_playMode == EPlayMode.HostPlayMode) + { + return _hostPlayModeImpl.UpdateStaticVersionAsync(packageName, timeout); + } + else + { + throw new NotImplementedException(); + } + } + + /// + /// 向网络端请求并更新补丁清单 + /// + /// 更新的资源包裹名称 + /// 更新的资源包裹版本 + /// 超时时间(默认值:60秒) + public UpdateManifestOperation UpdateManifestAsync(string packageName, string packageCRC, int timeout = 60) + { + DebugCheckInitialize(); + DebugCheckUpdateManifest(); + if (_playMode == EPlayMode.EditorSimulateMode) + { + var operation = new EditorPlayModeUpdateManifestOperation(); + OperationSystem.StartOperation(operation); + return operation; + } + else if (_playMode == EPlayMode.OfflinePlayMode) + { + var operation = new OfflinePlayModeUpdateManifestOperation(); + OperationSystem.StartOperation(operation); + return operation; + } + else if (_playMode == EPlayMode.HostPlayMode) + { + return _hostPlayModeImpl.UpdatePatchManifestAsync(packageName, packageCRC, timeout); + } + else + { + throw new NotImplementedException(); + } + } + + /// + /// 弱联网情况下加载补丁清单 + /// 注意:当指定版本内容验证失败后会返回失败。 + /// + /// 指定的资源包裹名称 + /// 指定的资源包裹版本 + public UpdateManifestOperation WeaklyUpdateManifestAsync(string packageName, string packageCRC) + { + DebugCheckInitialize(); + if (_playMode == EPlayMode.EditorSimulateMode) + { + var operation = new EditorPlayModeUpdateManifestOperation(); + OperationSystem.StartOperation(operation); + return operation; + } + else if (_playMode == EPlayMode.OfflinePlayMode) + { + var operation = new OfflinePlayModeUpdateManifestOperation(); + OperationSystem.StartOperation(operation); + return operation; + } + else if (_playMode == EPlayMode.HostPlayMode) + { + return _hostPlayModeImpl.WeaklyUpdatePatchManifestAsync(packageName, packageCRC); + } + else + { + throw new NotImplementedException(); + } + } + + /// + /// 开启一个异步操作 + /// + /// 异步操作对象 + public void StartOperation(GameAsyncOperation operation) + { + OperationSystem.StartOperation(operation); + } + + /// + /// 资源回收(卸载引用计数为零的资源) + /// + public void UnloadUnusedAssets() + { + if (_isInitialize) + { + AssetSystem.Update(); + AssetSystem.UnloadUnusedAssets(); + } + } + + /// + /// 强制回收所有资源 + /// + public void ForceUnloadAllAssets() + { + if (_isInitialize) + { + AssetSystem.ForceUnloadAllAssets(); + } + } + + + #region 资源信息 + /// + /// 是否需要从远端更新下载 + /// + /// 资源的定位地址 + public bool IsNeedDownloadFromRemote(string location) + { + DebugCheckInitialize(); + AssetInfo assetInfo = ConvertLocationToAssetInfo(location, null); + if (assetInfo.IsInvalid) + return false; + + BundleInfo bundleInfo = _bundleServices.GetBundleInfo(assetInfo); + if (bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromRemote) + return true; + else + return false; + } + + /// + /// 是否需要从远端更新下载 + /// + /// 资源的定位地址 + public bool IsNeedDownloadFromRemote(AssetInfo assetInfo) + { + DebugCheckInitialize(); + if (assetInfo.IsInvalid) + { + YooLogger.Warning(assetInfo.Error); + return false; + } + + BundleInfo bundleInfo = _bundleServices.GetBundleInfo(assetInfo); + if (bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromRemote) + return true; + else + return false; + } + + /// + /// 获取资源信息列表 + /// + /// 资源标签 + public AssetInfo[] GetAssetInfos(string tag) + { + DebugCheckInitialize(); + string[] tags = new string[] { tag }; + return _bundleServices.GetAssetInfos(tags); + } + + /// + /// 获取资源信息列表 + /// + /// 资源标签列表 + public AssetInfo[] GetAssetInfos(string[] tags) + { + DebugCheckInitialize(); + return _bundleServices.GetAssetInfos(tags); + } + + /// + /// 获取资源信息 + /// + /// 资源的定位地址 + public AssetInfo GetAssetInfo(string location) + { + DebugCheckInitialize(); + AssetInfo assetInfo = ConvertLocationToAssetInfo(location, null); + return assetInfo; + } + + /// + /// 获取资源路径 + /// + /// 资源的定位地址 + /// 如果location地址无效,则返回空字符串 + public string GetAssetPath(string location) + { + DebugCheckInitialize(); + return _locationServices.ConvertLocationToAssetPath(location); + } + #endregion + + #region 原生文件 + /// + /// 异步获取原生文件 + /// + /// 资源的定位地址 + /// 拷贝路径 + public RawFileOperation GetRawFileAsync(string location, string copyPath = null) + { + DebugCheckInitialize(); + AssetInfo assetInfo = ConvertLocationToAssetInfo(location, null); + return GetRawFileInternal(assetInfo, copyPath); + } + + /// + /// 异步获取原生文件 + /// + /// 资源信息 + /// 拷贝路径 + public RawFileOperation GetRawFileAsync(AssetInfo assetInfo, string copyPath = null) + { + DebugCheckInitialize(); + if (assetInfo.IsInvalid) + YooLogger.Warning(assetInfo.Error); + return GetRawFileInternal(assetInfo, copyPath); + } + + + private RawFileOperation GetRawFileInternal(AssetInfo assetInfo, string copyPath) + { + if (assetInfo.IsInvalid) + { + RawFileOperation operation = new CompletedRawFileOperation(assetInfo.Error, copyPath); + OperationSystem.StartOperation(operation); + return operation; + } + + BundleInfo bundleInfo = _bundleServices.GetBundleInfo(assetInfo); + +#if UNITY_EDITOR + if (bundleInfo.Bundle.IsRawFile == false) + { + string error = $"Cannot load asset bundle file using {nameof(GetRawFileAsync)} method !"; + YooLogger.Error(error); + RawFileOperation operation = new CompletedRawFileOperation(error, copyPath); + OperationSystem.StartOperation(operation); + return operation; + } +#endif + + if (_playMode == EPlayMode.EditorSimulateMode) + { + RawFileOperation operation = new EditorPlayModeRawFileOperation(bundleInfo, copyPath); + OperationSystem.StartOperation(operation); + return operation; + } + else if (_playMode == EPlayMode.OfflinePlayMode) + { + RawFileOperation operation = new OfflinePlayModeRawFileOperation(bundleInfo, copyPath); + OperationSystem.StartOperation(operation); + return operation; + } + else if (_playMode == EPlayMode.HostPlayMode) + { + RawFileOperation operation = new HostPlayModeRawFileOperation(bundleInfo, copyPath); + OperationSystem.StartOperation(operation); + return operation; + } + else + { + throw new NotImplementedException(); + } + } + #endregion + + #region 场景加载 + /// + /// 异步加载场景 + /// + /// 场景的定位地址 + /// 场景加载模式 + /// 加载完毕时是否主动激活 + /// 优先级 + public SceneOperationHandle LoadSceneAsync(string location, LoadSceneMode sceneMode = LoadSceneMode.Single, bool activateOnLoad = true, int priority = 100) + { + DebugCheckInitialize(); + AssetInfo assetInfo = ConvertLocationToAssetInfo(location, null); + var handle = AssetSystem.LoadSceneAsync(assetInfo, sceneMode, activateOnLoad, priority); + return handle; + } + + /// + /// 异步加载场景 + /// + /// 场景的资源信息 + /// 场景加载模式 + /// 加载完毕时是否主动激活 + /// 优先级 + public SceneOperationHandle LoadSceneAsync(AssetInfo assetInfo, LoadSceneMode sceneMode = LoadSceneMode.Single, bool activateOnLoad = true, int priority = 100) + { + DebugCheckInitialize(); + if (assetInfo.IsInvalid) + YooLogger.Warning(assetInfo.Error); + var handle = AssetSystem.LoadSceneAsync(assetInfo, sceneMode, activateOnLoad, priority); + return handle; + } + #endregion + + #region 资源加载 + /// + /// 同步加载资源对象 + /// + /// 资源信息 + public AssetOperationHandle LoadAssetSync(AssetInfo assetInfo) + { + DebugCheckInitialize(); + if (assetInfo.IsInvalid) + YooLogger.Warning(assetInfo.Error); + return LoadAssetInternal(assetInfo, true); + } + + /// + /// 同步加载资源对象 + /// + /// 资源类型 + /// 资源的定位地址 + public AssetOperationHandle LoadAssetSync(string location) where TObject : UnityEngine.Object + { + DebugCheckInitialize(); + AssetInfo assetInfo = ConvertLocationToAssetInfo(location, typeof(TObject)); + return LoadAssetInternal(assetInfo, true); + } + + /// + /// 同步加载资源对象 + /// + /// 资源的定位地址 + /// 资源类型 + public AssetOperationHandle LoadAssetSync(string location, System.Type type) + { + DebugCheckInitialize(); + AssetInfo assetInfo = ConvertLocationToAssetInfo(location, type); + return LoadAssetInternal(assetInfo, true); + } + + + /// + /// 异步加载资源对象 + /// + /// 资源信息 + public AssetOperationHandle LoadAssetAsync(AssetInfo assetInfo) + { + DebugCheckInitialize(); + if (assetInfo.IsInvalid) + YooLogger.Warning(assetInfo.Error); + return LoadAssetInternal(assetInfo, false); + } + + /// + /// 异步加载资源对象 + /// + /// 资源类型 + /// 资源的定位地址 + public AssetOperationHandle LoadAssetAsync(string location) where TObject : UnityEngine.Object + { + DebugCheckInitialize(); + AssetInfo assetInfo = ConvertLocationToAssetInfo(location, typeof(TObject)); + return LoadAssetInternal(assetInfo, false); + } + + /// + /// 异步加载资源对象 + /// + /// 资源的定位地址 + /// 资源类型 + public AssetOperationHandle LoadAssetAsync(string location, System.Type type) + { + DebugCheckInitialize(); + AssetInfo assetInfo = ConvertLocationToAssetInfo(location, type); + return LoadAssetInternal(assetInfo, false); + } + + + private AssetOperationHandle LoadAssetInternal(AssetInfo assetInfo, bool waitForAsyncComplete) + { +#if UNITY_EDITOR + BundleInfo bundleInfo = _bundleServices.GetBundleInfo(assetInfo); + if (bundleInfo.Bundle.IsRawFile) + { + string error = $"Cannot load raw file using LoadAsset method !"; + YooLogger.Error(error); + CompletedProvider completedProvider = new CompletedProvider(assetInfo); + completedProvider.SetCompleted(error); + return completedProvider.CreateHandle(); + } +#endif + + var handle = AssetSystem.LoadAssetAsync(assetInfo); + if (waitForAsyncComplete) + handle.WaitForAsyncComplete(); + return handle; + } + #endregion + + #region 资源加载 + /// + /// 同步加载子资源对象 + /// + /// 资源信息 + public SubAssetsOperationHandle LoadSubAssetsSync(AssetInfo assetInfo) + { + DebugCheckInitialize(); + if (assetInfo.IsInvalid) + YooLogger.Warning(assetInfo.Error); + return LoadSubAssetsInternal(assetInfo, true); + } + + /// + /// 同步加载子资源对象 + /// + /// 资源类型 + /// 资源的定位地址 + public SubAssetsOperationHandle LoadSubAssetsSync(string location) where TObject : UnityEngine.Object + { + DebugCheckInitialize(); + AssetInfo assetInfo = ConvertLocationToAssetInfo(location, typeof(TObject)); + return LoadSubAssetsInternal(assetInfo, true); + } + + /// + /// 同步加载子资源对象 + /// + /// 资源的定位地址 + /// 子对象类型 + public SubAssetsOperationHandle LoadSubAssetsSync(string location, System.Type type) + { + DebugCheckInitialize(); + AssetInfo assetInfo = ConvertLocationToAssetInfo(location, type); + return LoadSubAssetsInternal(assetInfo, true); + } + + + /// + /// 异步加载子资源对象 + /// + /// 资源信息 + public SubAssetsOperationHandle LoadSubAssetsAsync(AssetInfo assetInfo) + { + DebugCheckInitialize(); + if (assetInfo.IsInvalid) + YooLogger.Warning(assetInfo.Error); + return LoadSubAssetsInternal(assetInfo, false); + } + + /// + /// 异步加载子资源对象 + /// + /// 资源类型 + /// 资源的定位地址 + public SubAssetsOperationHandle LoadSubAssetsAsync(string location) where TObject : UnityEngine.Object + { + DebugCheckInitialize(); + AssetInfo assetInfo = ConvertLocationToAssetInfo(location, typeof(TObject)); + return LoadSubAssetsInternal(assetInfo, false); + } + + /// + /// 异步加载子资源对象 + /// + /// 资源的定位地址 + /// 子对象类型 + public SubAssetsOperationHandle LoadSubAssetsAsync(string location, System.Type type) + { + DebugCheckInitialize(); + AssetInfo assetInfo = ConvertLocationToAssetInfo(location, type); + return LoadSubAssetsInternal(assetInfo, false); + } + + + private SubAssetsOperationHandle LoadSubAssetsInternal(AssetInfo assetInfo, bool waitForAsyncComplete) + { +#if UNITY_EDITOR + BundleInfo bundleInfo = _bundleServices.GetBundleInfo(assetInfo); + if (bundleInfo.Bundle.IsRawFile) + { + string error = $"Cannot load raw file using LoadSubAssets method !"; + YooLogger.Error(error); + CompletedProvider completedProvider = new CompletedProvider(assetInfo); + completedProvider.SetCompleted(error); + return completedProvider.CreateHandle(); + } +#endif + + var handle = AssetSystem.LoadSubAssetsAsync(assetInfo); + if (waitForAsyncComplete) + handle.WaitForAsyncComplete(); + return handle; + } + #endregion + + #region 资源下载 + /// + /// 创建补丁下载器,用于下载更新资源标签指定的资源包文件 + /// + /// 资源标签 + /// 同时下载的最大文件数 + /// 下载失败的重试次数 + public PatchDownloaderOperation CreatePatchDownloader(string tag, int downloadingMaxNumber, int failedTryAgain) + { + DebugCheckInitialize(); + return CreatePatchDownloader(new string[] { tag }, downloadingMaxNumber, failedTryAgain); + } + + /// + /// 创建补丁下载器,用于下载更新资源标签指定的资源包文件 + /// + /// 资源标签列表 + /// 同时下载的最大文件数 + /// 下载失败的重试次数 + public PatchDownloaderOperation CreatePatchDownloader(string[] tags, int downloadingMaxNumber, int failedTryAgain) + { + DebugCheckInitialize(); + if (_playMode == EPlayMode.EditorSimulateMode || _playMode == EPlayMode.OfflinePlayMode) + { + List downloadList = new List(); + var operation = new PatchDownloaderOperation(downloadList, downloadingMaxNumber, failedTryAgain); + return operation; + } + else if (_playMode == EPlayMode.HostPlayMode) + { + return _hostPlayModeImpl.CreatePatchDownloaderByTags(tags, downloadingMaxNumber, failedTryAgain); + } + else + { + throw new NotImplementedException(); + } + } + + /// + /// 创建补丁下载器,用于下载更新当前资源版本所有的资源包文件 + /// + /// 同时下载的最大文件数 + /// 下载失败的重试次数 + public PatchDownloaderOperation CreatePatchDownloader(int downloadingMaxNumber, int failedTryAgain) + { + DebugCheckInitialize(); + if (_playMode == EPlayMode.EditorSimulateMode || _playMode == EPlayMode.OfflinePlayMode) + { + List downloadList = new List(); + var operation = new PatchDownloaderOperation(downloadList, downloadingMaxNumber, failedTryAgain); + return operation; + } + else if (_playMode == EPlayMode.HostPlayMode) + { + return _hostPlayModeImpl.CreatePatchDownloaderByAll(downloadingMaxNumber, failedTryAgain); + } + else + { + throw new NotImplementedException(); + } + } + + + /// + /// 创建补丁下载器,用于下载更新指定的资源列表依赖的资源包文件 + /// + /// 资源定位列表 + /// 同时下载的最大文件数 + /// 下载失败的重试次数 + public PatchDownloaderOperation CreateBundleDownloader(string[] locations, int downloadingMaxNumber, int failedTryAgain) + { + DebugCheckInitialize(); + if (_playMode == EPlayMode.EditorSimulateMode || _playMode == EPlayMode.OfflinePlayMode) + { + List downloadList = new List(); + var operation = new PatchDownloaderOperation(downloadList, downloadingMaxNumber, failedTryAgain); + return operation; + } + else if (_playMode == EPlayMode.HostPlayMode) + { + List assetInfos = new List(locations.Length); + foreach (var location in locations) + { + AssetInfo assetInfo = ConvertLocationToAssetInfo(location, null); + assetInfos.Add(assetInfo); + } + return _hostPlayModeImpl.CreatePatchDownloaderByPaths(assetInfos.ToArray(), downloadingMaxNumber, failedTryAgain); + } + else + { + throw new NotImplementedException(); + } + } + + /// + /// 创建补丁下载器,用于下载更新指定的资源列表依赖的资源包文件 + /// + /// 资源信息列表 + /// 同时下载的最大文件数 + /// 下载失败的重试次数 + public PatchDownloaderOperation CreateBundleDownloader(AssetInfo[] assetInfos, int downloadingMaxNumber, int failedTryAgain) + { + DebugCheckInitialize(); + if (_playMode == EPlayMode.EditorSimulateMode || _playMode == EPlayMode.OfflinePlayMode) + { + List downloadList = new List(); + var operation = new PatchDownloaderOperation(downloadList, downloadingMaxNumber, failedTryAgain); + return operation; + } + else if (_playMode == EPlayMode.HostPlayMode) + { + return _hostPlayModeImpl.CreatePatchDownloaderByPaths(assetInfos, downloadingMaxNumber, failedTryAgain); + } + else + { + throw new NotImplementedException(); + } + } + #endregion + + #region 资源解压 + /// + /// 创建补丁解压器 + /// + /// 资源标签 + /// 同时解压的最大文件数 + /// 解压失败的重试次数 + public PatchUnpackerOperation CreatePatchUnpacker(string tag, int unpackingMaxNumber, int failedTryAgain) + { + DebugCheckInitialize(); + return CreatePatchUnpacker(new string[] { tag }, unpackingMaxNumber, failedTryAgain); + } + + /// + /// 创建补丁解压器 + /// + /// 资源标签列表 + /// 同时解压的最大文件数 + /// 解压失败的重试次数 + public PatchUnpackerOperation CreatePatchUnpacker(string[] tags, int unpackingMaxNumber, int failedTryAgain) + { + DebugCheckInitialize(); + if (_playMode == EPlayMode.EditorSimulateMode) + { + List downloadList = new List(); + var operation = new PatchUnpackerOperation(downloadList, unpackingMaxNumber, failedTryAgain); + return operation; + } + else if (_playMode == EPlayMode.OfflinePlayMode) + { + List downloadList = new List(); + var operation = new PatchUnpackerOperation(downloadList, unpackingMaxNumber, failedTryAgain); + return operation; + } + else if (_playMode == EPlayMode.HostPlayMode) + { + return _hostPlayModeImpl.CreatePatchUnpackerByTags(tags, unpackingMaxNumber, failedTryAgain); + } + else + { + throw new NotImplementedException(); + } + } + + /// + /// 创建补丁解压器 + /// + /// 同时解压的最大文件数 + /// 解压失败的重试次数 + public PatchUnpackerOperation CreatePatchUnpacker(int unpackingMaxNumber, int failedTryAgain) + { + DebugCheckInitialize(); + if (_playMode == EPlayMode.EditorSimulateMode) + { + List downloadList = new List(); + var operation = new PatchUnpackerOperation(downloadList, unpackingMaxNumber, failedTryAgain); + return operation; + } + else if (_playMode == EPlayMode.OfflinePlayMode) + { + List downloadList = new List(); + var operation = new PatchUnpackerOperation(downloadList, unpackingMaxNumber, failedTryAgain); + return operation; + } + else if (_playMode == EPlayMode.HostPlayMode) + { + return _hostPlayModeImpl.CreatePatchUnpackerByAll(unpackingMaxNumber, failedTryAgain); + } + else + { + throw new NotImplementedException(); + } + } + #endregion + + #region 包裹更新 + /// + /// 创建资源包裹下载器,用于下载更新指定资源版本所有的资源包文件 + /// + /// 指定更新的资源包裹名称 + /// 指定更新的资源包裹版本 + /// 超时时间 + public UpdatePackageOperation UpdatePackageAsync(string packageName, string packageCRC, int timeout = 60) + { + DebugCheckInitialize(); + if (_playMode == EPlayMode.EditorSimulateMode) + { + var operation = new EditorPlayModeUpdatePackageOperation(); + OperationSystem.StartOperation(operation); + return operation; + } + else if (_playMode == EPlayMode.OfflinePlayMode) + { + var operation = new OfflinePlayModeUpdatePackageOperation(); + OperationSystem.StartOperation(operation); + return operation; + } + else if (_playMode == EPlayMode.HostPlayMode) + { + return _hostPlayModeImpl.UpdatePackageAsync(packageName, packageCRC, timeout); + } + else + { + throw new NotImplementedException(); + } + } + #endregion + + #region 沙盒相关 + /// + /// 获取沙盒的根路径 + /// + public string GetSandboxRoot() + { + return PathHelper.MakePersistentRootPath(); + } + + /// + /// 清空沙盒目录 + /// + public void ClearSandbox() + { + SandboxHelper.DeleteSandbox(); + } + + /// + /// 清空所有的缓存文件 + /// + public void ClearAllCacheFiles() + { + SandboxHelper.DeleteCacheFolder(); + } + + /// + /// 清空未被使用的缓存文件 + /// + public ClearUnusedCacheFilesOperation ClearUnusedCacheFiles() + { + DebugCheckInitialize(); + if (_playMode == EPlayMode.EditorSimulateMode) + { + var operation = new EditorPlayModeClearUnusedCacheFilesOperation(); + OperationSystem.StartOperation(operation); + return operation; + } + else if (_playMode == EPlayMode.OfflinePlayMode) + { + var operation = new OfflinePlayModeClearUnusedCacheFilesOperation(); + OperationSystem.StartOperation(operation); + return operation; + } + else if (_playMode == EPlayMode.HostPlayMode) + { + var operation = new HostPlayModeClearUnusedCacheFilesOperation(_hostPlayModeImpl); + OperationSystem.StartOperation(operation); + return operation; + } + else + { + throw new NotImplementedException(); + } + } + #endregion + + #region 内部方法 + internal void InternalDestroy() + { + if (_isInitialize) + { + _isInitialize = false; + _initializeError = string.Empty; + _initializeStatus = EOperationStatus.None; + + _bundleServices = null; + _locationServices = null; + _editorSimulateModeImpl = null; + _offlinePlayModeImpl = null; + _hostPlayModeImpl = null; + + OperationSystem.DestroyAll(); + DownloadSystem.DestroyAll(); + CacheSystem.DestroyAll(); + AssetSystem.DestroyAll(); + YooLogger.Log("YooAssets destroy all !"); + } + } + internal void InternalUpdate() + { + OperationSystem.Update(); + DownloadSystem.Update(); + AssetSystem.Update(); + } + + /// + /// 资源定位地址转换为资源完整路径 + /// + internal string MappingToAssetPath(string location) + { + return _bundleServices.MappingToAssetPath(location); + } + #endregion + + #region 调试方法 + [Conditional("DEBUG")] + private void DebugCheckInitialize() + { + if (_initializeStatus == EOperationStatus.None) + throw new Exception("YooAssets initialize not completed !"); + else if (_initializeStatus == EOperationStatus.Failed) + throw new Exception($"YooAssets initialize failed : {_initializeError}"); + } + + [Conditional("DEBUG")] + private void DebugCheckLocation(string location) + { + if (string.IsNullOrEmpty(location) == false) + { + // 检查路径末尾是否有空格 + int index = location.LastIndexOf(" "); + if (index != -1) + { + if (location.Length == index + 1) + YooLogger.Warning($"Found blank character in location : \"{location}\""); + } + + if (location.IndexOfAny(System.IO.Path.GetInvalidPathChars()) >= 0) + YooLogger.Warning($"Found illegal character in location : \"{location}\""); + } + } + + [Conditional("DEBUG")] + private void DebugCheckUpdateManifest() + { + var loadedBundleInfos = AssetSystem.GetLoadedBundleInfos(); + if (loadedBundleInfos.Count > 0) + { + YooLogger.Warning($"Found loaded bundle before update manifest ! Recommended to call the {nameof(ForceUnloadAllAssets)} method to release loaded bundle !"); + } + } + #endregion + + #region 私有方法 + /// + /// 资源定位地址转换为资源信息类,失败时内部会发出错误日志。 + /// + /// 如果转换失败会返回一个无效的资源信息类 + private AssetInfo ConvertLocationToAssetInfo(string location, System.Type assetType) + { + DebugCheckLocation(location); + string assetPath = _locationServices.ConvertLocationToAssetPath(location); + PatchAsset patchAsset = _bundleServices.TryGetPatchAsset(assetPath); + if (patchAsset != null) + { + AssetInfo assetInfo = new AssetInfo(patchAsset, assetType); + return assetInfo; + } + else + { + string error; + if (string.IsNullOrEmpty(location)) + error = $"The location is null or empty !"; + else + error = $"The location is invalid : {location}"; + YooLogger.Error(error); + AssetInfo assetInfo = new AssetInfo(error); + return assetInfo; + } + } + #endregion + } +} \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/YooAssetComponent.cs.meta b/Assets/YooAsset/Runtime/YooAssetComponent.cs.meta new file mode 100644 index 0000000..8878911 --- /dev/null +++ b/Assets/YooAsset/Runtime/YooAssetComponent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6fcda791b973f5b4499e8bd3ede91312 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: