internal override void Update() { if (_steps == ESteps.Builder) { _simulatePatchManifestPath = EditorSimulateModeHelper.SimulateBuild(); if (string.IsNullOrEmpty(_simulatePatchManifestPath)) { _steps = ESteps.Done; Status = EOperationStatus.Failed; Error = "Simulate build failed, see the detail info on the console window."; return; } _steps = ESteps.Load; } if (_steps == ESteps.Load) { if (File.Exists(_simulatePatchManifestPath) == false) { _steps = ESteps.Done; Status = EOperationStatus.Failed; Error = $"Manifest file not found : {_simulatePatchManifestPath}"; return; } YooLogger.Log($"Load manifest file : {_simulatePatchManifestPath}"); string jsonContent = FileUtility.ReadFile(_simulatePatchManifestPath); var simulatePatchManifest = PatchManifest.Deserialize(jsonContent); _impl.SetSimulatePatchManifest(simulatePatchManifest); _steps = ESteps.Done; Status = EOperationStatus.Succeed; } }
/// <summary> /// 清空未被使用的缓存文件 /// </summary> public void ClearUnusedCacheFiles() { string cacheFolderPath = SandboxHelper.GetCacheFolderPath(); if (Directory.Exists(cacheFolderPath) == false) { return; } DirectoryInfo directoryInfo = new DirectoryInfo(cacheFolderPath); foreach (FileInfo fileInfo in directoryInfo.GetFiles()) { bool used = false; foreach (var patchBundle in LocalPatchManifest.BundleList) { if (fileInfo.Name == patchBundle.Hash) { used = true; break; } } if (used == false) { YooLogger.Log($"Delete unused cache file : {fileInfo.Name}"); File.Delete(fileInfo.FullName); } } }
/// <summary> /// 主线程等待异步操作完毕 /// </summary> public override void WaitForAsyncComplete() { _isWaitForAsyncComplete = true; int frame = 1000; while (true) { // 保险机制 // 注意:如果需要从WEB端下载资源,可能会触发保险机制! frame--; if (frame == 0) { if (_isShowWaitForAsyncError == false) { _isShowWaitForAsyncError = true; YooLogger.Error($"WaitForAsyncComplete failed ! BundleName : {MainBundleInfo.BundleName} States : {Status}"); } break; } // 驱动流程 Update(); // 完成后退出 if (IsDone()) { break; } } }
private static 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); } }
/// <summary> /// 加载子资源对象 /// </summary> public static SubAssetsOperationHandle LoadSubAssetsAsync(AssetInfo assetInfo) { if (assetInfo.IsInvalid) { YooLogger.Warning(assetInfo.Error); CompletedProvider completedProvider = new CompletedProvider(assetInfo); return(completedProvider.CreateHandle <SubAssetsOperationHandle>()); } ProviderBase provider = TryGetProvider(assetInfo.ProviderGUID); if (provider == null) { if (_simulationOnEditor) { provider = new DatabaseSubAssetsProvider(assetInfo); } else { provider = new BundledSubAssetsProvider(assetInfo); } provider.InitSpawnDebugInfo(); _providers.Add(provider); } return(provider.CreateHandle <SubAssetsOperationHandle>()); }
/// <summary> /// 异步卸载子场景 /// </summary> public UnloadSceneOperation UnloadAsync() { // 如果句柄无效 if (IsValid == false) { string error = $"{nameof(SceneOperationHandle)} is invalid."; var operation = new UnloadSceneOperation(error); OperationSystem.StartOperaiton(operation); return(operation); } // 如果是主场景 if (IsMainScene()) { string error = $"Cannot unload main scene. Use {nameof(YooAssets.LoadSceneAsync)} method to change the main scene !"; YooLogger.Error(error); var operation = new UnloadSceneOperation(error); OperationSystem.StartOperaiton(operation); return(operation); } // 卸载子场景 Scene sceneObject = SceneObject; AssetSystem.UnloadSubScene(Provider); { var operation = new UnloadSceneOperation(sceneObject); OperationSystem.StartOperaiton(operation); return(operation); } }
private static RawFileOperation GetRawFileInternal(AssetInfo assetInfo, string copyPath) { if (assetInfo.IsInvalid) { YooLogger.Warning(assetInfo.Error); RawFileOperation operation = new CompletedRawFileOperation(assetInfo.Error, copyPath); OperationSystem.StartOperaiton(operation); return(operation); } BundleInfo bundleInfo = _bundleServices.GetBundleInfo(assetInfo); if (_playMode == EPlayMode.EditorSimulateMode) { RawFileOperation operation = new EditorPlayModeRawFileOperation(bundleInfo, copyPath); OperationSystem.StartOperaiton(operation); return(operation); } else if (_playMode == EPlayMode.OfflinePlayMode) { RawFileOperation operation = new OfflinePlayModeRawFileOperation(bundleInfo, copyPath); OperationSystem.StartOperaiton(operation); return(operation); } else if (_playMode == EPlayMode.HostPlayMode) { RawFileOperation operation = new HostPlayModeRawFileOperation(bundleInfo, copyPath); OperationSystem.StartOperaiton(operation); return(operation); } else { throw new NotImplementedException(); } }
private List <BundleInfo> GetDownloadListByPaths(AssetInfo[] assetInfos) { // 获取资源对象的资源包和所有依赖资源包 List <PatchBundle> checkList = new List <PatchBundle>(); foreach (var assetInfo in assetInfos) { if (assetInfo.IsInvalid) { YooLogger.Warning(assetInfo.Error); continue; } string mainBundleName = LocalPatchManifest.GetBundleName(assetInfo.AssetPath); if (LocalPatchManifest.Bundles.TryGetValue(mainBundleName, out PatchBundle mainBundle)) { if (checkList.Contains(mainBundle) == false) { checkList.Add(mainBundle); } } string[] dependBundleNames = LocalPatchManifest.GetAllDependencies(assetInfo.AssetPath); foreach (var dependBundleName in dependBundleNames) { if (LocalPatchManifest.Bundles.TryGetValue(dependBundleName, out PatchBundle dependBundle)) { if (checkList.Contains(dependBundle) == false) { checkList.Add(dependBundle); } } } } List <PatchBundle> downloadList = new List <PatchBundle>(1000); foreach (var patchBundle in checkList) { // 忽略缓存文件 if (DownloadSystem.ContainsVerifyFile(patchBundle.Hash)) { continue; } // 忽略APP资源 // 注意:如果是APP资源并且哈希值相同,则不需要下载 if (AppPatchManifest.Bundles.TryGetValue(patchBundle.BundleName, out PatchBundle appPatchBundle)) { if (appPatchBundle.IsBuildin && appPatchBundle.Hash == patchBundle.Hash) { continue; } } downloadList.Add(patchBundle); } return(ConvertToDownloadList(downloadList)); }
/// <summary> /// 开始下载资源文件 /// 注意:只有第一次请求的参数才是有效的 /// </summary> public static DownloaderBase BeginDownload(BundleInfo bundleInfo, int failedTryAgain, int timeout = 60) { // 查询存在的下载器 if (_downloaderDic.TryGetValue(bundleInfo.Hash, out var downloader)) { return(downloader); } // 如果资源已经缓存 if (ContainsVerifyFile(bundleInfo.Hash)) { var tempDownloader = new TempDownloader(bundleInfo); return(tempDownloader); } // 创建新的下载器 { YooLogger.Log($"Beginning to download file : {bundleInfo.BundleName} URL : {bundleInfo.RemoteMainURL}"); FileUtility.CreateFileDirectory(bundleInfo.GetCacheLoadPath()); DownloaderBase newDownloader; if (bundleInfo.SizeBytes >= _breakpointResumeFileSize) { newDownloader = new HttpDownloader(bundleInfo); } else { newDownloader = new FileDownloader(bundleInfo); } newDownloader.SendRequest(failedTryAgain, timeout); _downloaderDic.Add(bundleInfo.Hash, newDownloader); return(newDownloader); } }
/// <summary> /// 缓存验证过的文件 /// </summary> public static void CacheVerifyFile(string hash, string bundleName) { if (_cachedHashList.ContainsKey(hash) == false) { YooLogger.Log($"Cache verify file : {bundleName} Hash : {hash}"); _cachedHashList.Add(hash, bundleName); } }
/// <summary> /// 加载沙盒内的补丁清单 /// 注意:在加载本地补丁清单之前,已经验证过文件的哈希值 /// </summary> private void LoadSandboxPatchManifest(int updateResourceVersion) { YooLogger.Log("Load sandbox patch manifest file."); string filePath = PathHelper.MakePersistentLoadPath(YooAssetSettingsData.GetPatchManifestFileName(updateResourceVersion)); string jsonData = File.ReadAllText(filePath); var sandboxPatchManifest = PatchManifest.Deserialize(jsonData); _impl.SetLocalPatchManifest(sandboxPatchManifest); }
/// <summary> /// 获取调试信息 /// </summary> internal static void GetDebugReport(DebugReport report) { if (report == null) { YooLogger.Error($"{nameof(DebugReport)} is null"); } AssetSystem.GetDebugReport(report); }
public override void Update() { #if UNITY_EDITOR if (IsDone) { return; } if (Status == EStatus.None) { Status = EStatus.Loading; } // 1. 加载资源对象 if (Status == EStatus.Loading) { LoadSceneParameters loadSceneParameters = new LoadSceneParameters(); loadSceneParameters.loadSceneMode = SceneMode; _asyncOp = UnityEditor.SceneManagement.EditorSceneManager.LoadSceneAsyncInPlayMode(MainAssetInfo.AssetPath, loadSceneParameters); if (_asyncOp != null) { _asyncOp.allowSceneActivation = true; _asyncOp.priority = _priority; Status = EStatus.Checking; } else { Status = EStatus.Fail; LastError = $"Failed to load scene : {MainAssetInfo.AssetPath}"; YooLogger.Error(LastError); InvokeCompletion(); } } // 2. 检测加载结果 if (Status == EStatus.Checking) { if (_asyncOp.isDone) { SceneObject = SceneManager.GetSceneAt(SceneManager.sceneCount - 1); if (SceneObject.IsValid() && _activateOnLoad) { SceneManager.SetActiveScene(SceneObject); } Status = SceneObject.IsValid() ? EStatus.Success : EStatus.Fail; if (Status == EStatus.Fail) { LastError = $"The loaded scene is invalid : {MainAssetInfo.AssetPath}"; YooLogger.Error(LastError); } InvokeCompletion(); } } #endif }
/// <summary> /// 销毁所有下载器 /// </summary> public static void DestroyAll() { foreach (var valuePair in _downloaderDic) { var downloader = valuePair.Value; downloader.Abort(); } _downloaderDic.Clear(); YooLogger.Log("DownloadSystem destroy all !"); }
/// <summary> /// 更新缓存文件 /// </summary> public static void UpdateCache() { YooLogger.Log($"Update cache data to disk : {Application.version}"); CacheData cacheData = new CacheData(); cacheData.CacheAppVersion = Application.version; string filePath = GetCacheDataFilePath(); string jsonData = JsonUtility.ToJson(cacheData); FileUtility.CreateFile(filePath, jsonData); }
internal override void Update() { if (_steps == ESteps.None || _steps == ESteps.Done) { return; } if (_steps == ESteps.InitCache) { // 每次启动时比对APP版本号是否一致 CacheData cacheData = CacheData.LoadCache(); if (cacheData.CacheAppVersion != Application.version) { YooLogger.Warning($"Cache is dirty ! Cache application version is {cacheData.CacheAppVersion}, Current application version is {Application.version}"); // 注意:在覆盖安装的时候,会保留APP沙盒目录,可以选择清空缓存目录 if (_impl.ClearCacheWhenDirty) { YooLogger.Warning("Clear cache files."); SandboxHelper.DeleteCacheFolder(); } // 更新缓存文件 CacheData.UpdateCache(); } _steps = ESteps.Update; } if (_steps == ESteps.Update) { _appManifestLoader.Update(); Progress = _appManifestLoader.Progress(); if (_appManifestLoader.IsDone() == false) { return; } if (_appManifestLoader.Result == null) { _steps = ESteps.Done; Status = EOperationStatus.Failed; Error = _appManifestLoader.Error; } else { _steps = ESteps.Done; Status = EOperationStatus.Succeed; _impl.SetAppPatchManifest(_appManifestLoader.Result); _impl.SetLocalPatchManifest(_appManifestLoader.Result); } } }
/// <summary> /// 等待异步执行完毕 /// </summary> public void WaitForAsyncComplete() { IsWaitForAsyncComplete = true; // 注意:主动轮询更新完成同步加载 Update(); // 验证结果 if (IsDone == false) { YooLogger.Warning($"WaitForAsyncComplete failed to loading : {MainAssetInfo.AssetPath}"); } }
/// <summary> /// 加载配置文件 /// </summary> private static void LoadSettingData() { _setting = Resources.Load <YooAssetSettings>("YooAssetSettings"); if (_setting == null) { YooLogger.Log("YooAsset use default settings."); _setting = ScriptableObject.CreateInstance <YooAssetSettings>(); } else { YooLogger.Log("YooAsset use user settings."); } }
/// <summary> /// 解析远端请求的补丁清单 /// </summary> private bool ParseRemotePatchManifest(string content) { try { _remotePatchManifest = PatchManifest.Deserialize(content); return(true); } catch (Exception e) { YooLogger.Warning(e.ToString()); return(false); } }
internal override void Update() { if (_steps == ESteps.None || _steps == ESteps.Done) { return; } if (_steps == ESteps.LoadWebManifest) { string webURL = GetPatchManifestRequestURL(YooAssetSettingsData.GetPatchManifestFileName(_resourceVersion)); YooLogger.Log($"Beginning to request patch manifest : {webURL}"); _downloader = new UnityWebDataRequester(); _downloader.SendRequest(webURL, _timeout); _steps = ESteps.CheckWebManifest; } if (_steps == ESteps.CheckWebManifest) { Progress = _downloader.Progress(); if (_downloader.IsDone() == false) { return; } // Check error if (_downloader.HasError()) { _steps = ESteps.Done; Status = EOperationStatus.Failed; Error = _downloader.GetError(); } else { // 解析补丁清单 if (ParseRemotePatchManifest(_downloader.GetText())) { _steps = ESteps.Done; Status = EOperationStatus.Succeed; } else { _steps = ESteps.Done; Status = EOperationStatus.Failed; Error = $"URL : {_downloader.URL} Error : remote patch manifest content is invalid"; } } _downloader.Dispose(); } }
/// <summary> /// 释放操作句柄 /// </summary> public void ReleaseHandle(OperationHandleBase handle) { if (RefCount <= 0) { YooLogger.Warning("Asset provider reference count is already zero. There may be resource leaks !"); } if (_handles.Remove(handle) == false) { throw new System.Exception("Should never get here !"); } // 引用计数减少 RefCount--; }
/// <summary> /// 创建包裹下载器 /// </summary> public override PackageDownloaderOperation CreatePackageDownloader(int downloadingMaxNumber, int failedTryAgain) { if (Status == EOperationStatus.Succeed) { List <BundleInfo> downloadList = GetDownloadList(); var operation = new PackageDownloaderOperation(downloadList, downloadingMaxNumber, failedTryAgain); return(operation); } else { YooLogger.Error($"{nameof(UpdatePackageOperation)} status is failed !"); var operation = new PackageDownloaderOperation(null, downloadingMaxNumber, failedTryAgain); return(operation); } }
/// <summary> /// 获取文件的CRC32 /// </summary> public static string FileCRC32(string filePath) { try { using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)) { return(StreamCRC32(fs)); } } catch (Exception e) { YooLogger.Exception(e); return(string.Empty); } }
internal override void Update() { if (_steps == ESteps.None || _steps == ESteps.Done) { return; } if (_steps == ESteps.LoadStaticVersion) { string webURL = GetStaticVersionRequestURL(YooAssetSettings.VersionFileName); YooLogger.Log($"Beginning to request static version : {webURL}"); _downloader = new UnityWebDataRequester(); _downloader.SendRequest(webURL, _timeout); _steps = ESteps.CheckStaticVersion; } if (_steps == ESteps.CheckStaticVersion) { Progress = _downloader.Progress(); if (_downloader.IsDone() == false) { return; } if (_downloader.HasError()) { _steps = ESteps.Done; Status = EOperationStatus.Failed; Error = _downloader.GetError(); } else { if (int.TryParse(_downloader.GetText(), out int value)) { ResourceVersion = value; _steps = ESteps.Done; Status = EOperationStatus.Succeed; } else { _steps = ESteps.Done; Status = EOperationStatus.Failed; Error = $"URL : {_downloader.URL} Error : static version content is invalid."; } } _downloader.Dispose(); } }
/// <summary> /// 激活场景 /// </summary> public bool ActivateScene() { if (IsValid == false) { return(false); } if (SceneObject.IsValid() && SceneObject.isLoaded) { return(SceneManager.SetActiveScene(SceneObject)); } else { YooLogger.Warning($"Scene is invalid or not loaded : {SceneObject.name}"); return(false); } }
/// <summary> /// 解析并保存远端请求的补丁清单 /// </summary> private bool ParseAndSaveRemotePatchManifest(int updateResourceVersion, string content) { try { var remotePatchManifest = PatchManifest.Deserialize(content); _impl.SetLocalPatchManifest(remotePatchManifest); YooLogger.Log("Save remote patch manifest file."); string savePath = PathHelper.MakePersistentLoadPath(YooAssetSettingsData.GetPatchManifestFileName(updateResourceVersion)); PatchManifest.Serialize(savePath, remotePatchManifest); return(true); } catch (Exception e) { YooLogger.Error(e.ToString()); return(false); } }
/// <summary> /// 获取子资源对象 /// </summary> /// <typeparam name="TObject">子资源对象类型</typeparam> /// <param name="assetName">子资源对象名称</param> public TObject GetSubAssetObject <TObject>(string assetName) where TObject : UnityEngine.Object { if (IsValid == false) { return(null); } foreach (var assetObject in Provider.AllAssetObjects) { if (assetObject.name == assetName) { return(assetObject as TObject); } } YooLogger.Warning($"Not found sub asset object : {assetName}"); return(null); }
/// <summary> /// 加载场景 /// </summary> public static SceneOperationHandle LoadSceneAsync(AssetInfo assetInfo, LoadSceneMode sceneMode, bool activateOnLoad, int priority) { if (assetInfo.IsInvalid) { YooLogger.Warning(assetInfo.Error); CompletedProvider completedProvider = new CompletedProvider(assetInfo); return(completedProvider.CreateHandle <SceneOperationHandle>()); } // 注意:场景句柄永远保持唯一 string providerGUID = assetInfo.ProviderGUID; if (_sceneHandles.ContainsKey(providerGUID)) { return(_sceneHandles[providerGUID]); } // 如果加载的是主场景,则卸载所有缓存的场景 if (sceneMode == LoadSceneMode.Single) { UnloadAllScene(); } ProviderBase provider = TryGetProvider(providerGUID); if (provider == null) { if (_simulationOnEditor) { provider = new DatabaseSceneProvider(assetInfo, sceneMode, activateOnLoad, priority); } else { provider = new BundledSceneProvider(assetInfo, sceneMode, activateOnLoad, priority); } provider.InitSpawnDebugInfo(); _providers.Add(provider); } var handle = provider.CreateHandle <SceneOperationHandle>(); _sceneHandles.Add(providerGUID, handle); return(handle); }
/// <summary> /// 是否需要从远端更新下载 /// </summary> /// <param name="location">资源的定位地址</param> public static 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); } }
private static 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}\""); } } }