/// <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 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); } }
/// <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 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> /// 解析并保存远端请求的补丁清单 /// </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> public static bool ContainsVerifyFile(string hash) { if (_cachedHashList.ContainsKey(hash)) { string filePath = SandboxHelper.MakeCacheFilePath(hash); if (File.Exists(filePath)) { return(true); } else { string bundleName = _cachedHashList[hash]; _cachedHashList.Remove(hash); YooLogger.Error($"Cache file is missing : {bundleName} Hash : {hash}"); return(false); } } else { return(false); } }
/// <summary> /// 映射为资源路径 /// </summary> public string MappingToAssetPath(string location) { if (string.IsNullOrEmpty(location)) { YooLogger.Error("Failed to mapping location to asset path, The location is null or empty."); return(string.Empty); } if (_locationToLower) { location = location.ToLower(); } if (AssetPathMapping.TryGetValue(location, out string assetPath)) { return(assetPath); } else { YooLogger.Warning($"Failed to mapping location to asset path : {location}"); return(string.Empty); } }
public override void Update() { #if UNITY_EDITOR if (IsDone) { return; } if (Status == EStatus.None) { // 检测资源文件是否存在 string guid = UnityEditor.AssetDatabase.AssetPathToGUID(MainAssetInfo.AssetPath); if (string.IsNullOrEmpty(guid)) { Status = EStatus.Fail; LastError = $"Not found asset : {MainAssetInfo.AssetPath}"; YooLogger.Error(LastError); InvokeCompletion(); return; } Status = EStatus.Loading; // 注意:模拟异步加载效果提前返回 if (IsWaitForAsyncComplete == false) { return; } } // 1. 加载资源对象 if (Status == EStatus.Loading) { if (MainAssetInfo.AssetType == null) { AllAssetObjects = UnityEditor.AssetDatabase.LoadAllAssetRepresentationsAtPath(MainAssetInfo.AssetPath); } else { UnityEngine.Object[] findAssets = UnityEditor.AssetDatabase.LoadAllAssetRepresentationsAtPath(MainAssetInfo.AssetPath); List <UnityEngine.Object> result = new List <Object>(findAssets.Length); foreach (var findAsset in findAssets) { if (MainAssetInfo.AssetType.IsAssignableFrom(findAsset.GetType())) { result.Add(findAsset); } } AllAssetObjects = result.ToArray(); } Status = EStatus.Checking; } // 2. 检测加载结果 if (Status == EStatus.Checking) { Status = AllAssetObjects == null ? EStatus.Fail : EStatus.Success; if (Status == EStatus.Fail) { if (MainAssetInfo.AssetType == null) { LastError = $"Failed to load sub assets : {MainAssetInfo.AssetPath} AssetType : null"; } else { LastError = $"Failed to load sub assets : {MainAssetInfo.AssetPath} AssetType : {MainAssetInfo.AssetType}"; } YooLogger.Error(LastError); } InvokeCompletion(); } #endif }
/// <summary> /// 轮询更新 /// </summary> public override void Update() { if (_steps == ESteps.Done) { return; } if (_steps == ESteps.None) { if (MainBundleInfo.IsInvalid) { _steps = ESteps.Done; Status = EStatus.Failed; LastError = $"The bundle info is invalid : {MainBundleInfo.BundleName}"; YooLogger.Error(LastError); return; } if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromStreaming) { _steps = ESteps.LoadFile; _webURL = MainBundleInfo.GetStreamingLoadPath(); } else { throw new System.NotImplementedException(MainBundleInfo.LoadMode.ToString()); } } // 1. 从服务器或缓存中获取AssetBundle文件 if (_steps == ESteps.LoadFile) { string hash = StringUtility.RemoveExtension(MainBundleInfo.Hash); _webRequest = UnityWebRequestAssetBundle.GetAssetBundle(_webURL, Hash128.Parse(hash)); _webRequest.SendWebRequest(); _steps = ESteps.CheckFile; } // 2. 检测获取的AssetBundle文件 if (_steps == ESteps.CheckFile) { if (_webRequest.isDone == false) { return; } #if UNITY_2020_1_OR_NEWER if (_webRequest.result != UnityWebRequest.Result.Success) #else if (_webRequest.isNetworkError || _webRequest.isHttpError) #endif { YooLogger.Warning($"Failed to get asset bundle form web : {_webURL} Error : {_webRequest.error}"); _steps = ESteps.TryLoad; _tryTimer = 0; } else { CacheBundle = DownloadHandlerAssetBundle.GetContent(_webRequest); if (CacheBundle == null) { _steps = ESteps.Done; Status = EStatus.Failed; LastError = $"AssetBundle file is invalid : {MainBundleInfo.BundleName}"; YooLogger.Error(LastError); } else { _steps = ESteps.Done; Status = EStatus.Succeed; } } } // 3. 如果获取失败,重新尝试 if (_steps == ESteps.TryLoad) { _tryTimer += Time.unscaledDeltaTime; if (_tryTimer > 1f) { _webRequest.Dispose(); _webRequest = null; _steps = ESteps.LoadFile; } } }
public override void Update() { #if UNITY_EDITOR if (IsDone) { return; } if (Status == EStatus.None) { // 检测资源文件是否存在 string guid = UnityEditor.AssetDatabase.AssetPathToGUID(MainAssetInfo.AssetPath); if (string.IsNullOrEmpty(guid)) { Status = EStatus.Fail; LastError = $"Not found asset : {MainAssetInfo.AssetPath}"; YooLogger.Error(LastError); InvokeCompletion(); return; } Status = EStatus.Loading; // 注意:模拟异步加载效果提前返回 if (IsWaitForAsyncComplete == false) { return; } } // 1. 加载资源对象 if (Status == EStatus.Loading) { if (MainAssetInfo.AssetType == null) { AssetObject = UnityEditor.AssetDatabase.LoadMainAssetAtPath(MainAssetInfo.AssetPath); } else { AssetObject = UnityEditor.AssetDatabase.LoadAssetAtPath(MainAssetInfo.AssetPath, MainAssetInfo.AssetType); } Status = EStatus.Checking; } // 2. 检测加载结果 if (Status == EStatus.Checking) { Status = AssetObject == null ? EStatus.Fail : EStatus.Success; if (Status == EStatus.Fail) { if (MainAssetInfo.AssetType == null) { LastError = $"Failed to load asset object : {MainAssetInfo.AssetPath} AssetType : null"; } else { LastError = $"Failed to load asset object : {MainAssetInfo.AssetPath} AssetType : {MainAssetInfo.AssetType}"; } YooLogger.Error(LastError); } InvokeCompletion(); } #endif }
/// <summary> /// 初始化资源路径映射 /// </summary> public void InitAssetPathMapping(bool locationToLower) { if (_isInitAssetPathMapping) { return; } _isInitAssetPathMapping = true; if (EnableAddressable) { if (locationToLower) { YooLogger.Error("Addressable not support location to lower !"); } foreach (var patchAsset in AssetList) { string location = patchAsset.Address; if (AssetPathMapping.ContainsKey(location)) { throw new Exception($"Address have existed : {location}"); } else { AssetPathMapping.Add(location, patchAsset.AssetPath); } } } else { _locationToLower = locationToLower; foreach (var patchAsset in AssetList) { string location = patchAsset.AssetPath; if (locationToLower) { location = location.ToLower(); } // 添加原生路径的映射 if (AssetPathMapping.ContainsKey(location)) { throw new Exception($"AssetPath have existed : {location}"); } else { AssetPathMapping.Add(location, patchAsset.AssetPath); } // 添加无后缀名路径的映射 if (Path.HasExtension(location)) { string locationWithoutExtension = StringUtility.RemoveExtension(location); if (AssetPathMapping.ContainsKey(locationWithoutExtension)) { YooLogger.Warning($"AssetPath have existed : {locationWithoutExtension}"); } else { AssetPathMapping.Add(locationWithoutExtension, patchAsset.AssetPath); } } } } }
public override void Update() { if (IsDone) { return; } if (Status == EStatus.None) { Status = EStatus.CheckBundle; } // 1. 检测资源包 if (Status == EStatus.CheckBundle) { if (DependBundleGroup.IsDone() == false) { return; } if (OwnerBundle.IsDone() == false) { return; } if (DependBundleGroup.IsSucceed() == false) { Status = EStatus.Fail; LastError = DependBundleGroup.GetLastError(); InvokeCompletion(); return; } if (OwnerBundle.Status != AssetBundleLoaderBase.EStatus.Succeed) { Status = EStatus.Fail; LastError = OwnerBundle.LastError; InvokeCompletion(); return; } Status = EStatus.Loading; } // 2. 加载场景 if (Status == EStatus.Loading) { _asyncOp = SceneManager.LoadSceneAsync(_sceneName, SceneMode); if (_asyncOp != null) { _asyncOp.allowSceneActivation = true; _asyncOp.priority = _priority; Status = EStatus.Checking; } else { Status = EStatus.Fail; LastError = $"Failed to load scene : {_sceneName}"; YooLogger.Error(LastError); InvokeCompletion(); } } // 3. 检测加载结果 if (Status == EStatus.Checking) { if (_asyncOp.isDone) { SceneObject = SceneManager.GetSceneByName(_sceneName); if (SceneObject.IsValid() && _activateOnLoad) { SceneManager.SetActiveScene(SceneObject); } Status = SceneObject.IsValid() ? EStatus.Success : EStatus.Fail; if (Status == EStatus.Fail) { LastError = $"The load scene is invalid : {MainAssetInfo.AssetPath}"; YooLogger.Error(LastError); } InvokeCompletion(); } } }
public override void Update() { if (IsDone) { return; } if (Status == EStatus.None) { Status = EStatus.CheckBundle; } // 1. 检测资源包 if (Status == EStatus.CheckBundle) { if (IsWaitForAsyncComplete) { DependBundleGroup.WaitForAsyncComplete(); OwnerBundle.WaitForAsyncComplete(); } if (DependBundleGroup.IsDone() == false) { return; } if (OwnerBundle.IsDone() == false) { return; } if (DependBundleGroup.IsSucceed() == false) { Status = EStatus.Fail; LastError = DependBundleGroup.GetLastError(); InvokeCompletion(); return; } if (OwnerBundle.Status != AssetBundleLoaderBase.EStatus.Succeed) { Status = EStatus.Fail; LastError = OwnerBundle.LastError; InvokeCompletion(); return; } Status = EStatus.Loading; } // 2. 加载资源对象 if (Status == EStatus.Loading) { if (IsWaitForAsyncComplete) { if (MainAssetInfo.AssetType == null) { AssetObject = OwnerBundle.CacheBundle.LoadAsset(MainAssetInfo.AssetPath); } else { AssetObject = OwnerBundle.CacheBundle.LoadAsset(MainAssetInfo.AssetPath, MainAssetInfo.AssetType); } } else { if (MainAssetInfo.AssetType == null) { _cacheRequest = OwnerBundle.CacheBundle.LoadAssetAsync(MainAssetInfo.AssetPath); } else { _cacheRequest = OwnerBundle.CacheBundle.LoadAssetAsync(MainAssetInfo.AssetPath, MainAssetInfo.AssetType); } } Status = EStatus.Checking; } // 3. 检测加载结果 if (Status == EStatus.Checking) { if (_cacheRequest != null) { if (IsWaitForAsyncComplete) { // 强制挂起主线程(注意:该操作会很耗时) YooLogger.Warning("Suspend the main thread to load unity asset."); AssetObject = _cacheRequest.asset; } else { if (_cacheRequest.isDone == false) { return; } AssetObject = _cacheRequest.asset; } } Status = AssetObject == null ? EStatus.Fail : EStatus.Success; if (Status == EStatus.Fail) { if (MainAssetInfo.AssetType == null) { LastError = $"Failed to load asset : {MainAssetInfo.AssetPath} AssetType : null AssetBundle : {OwnerBundle.MainBundleInfo.BundleName}"; } else { LastError = $"Failed to load asset : {MainAssetInfo.AssetPath} AssetType : {MainAssetInfo.AssetType} AssetBundle : {OwnerBundle.MainBundleInfo.BundleName}"; } YooLogger.Error(LastError); } InvokeCompletion(); } }
/// <summary> /// 轮询更新 /// </summary> public override void Update() { if (_steps == ESteps.Done) { return; } if (_steps == ESteps.None) { if (MainBundleInfo.IsInvalid) { _steps = ESteps.Done; Status = EStatus.Failed; LastError = $"The bundle info is invalid : {MainBundleInfo.BundleName}"; YooLogger.Error(LastError); return; } if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromRemote) { _steps = ESteps.Download; _fileLoadPath = MainBundleInfo.GetCacheLoadPath(); } else if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromStreaming) { _steps = ESteps.LoadFile; _fileLoadPath = MainBundleInfo.GetStreamingLoadPath(); } else if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromCache) { _steps = ESteps.LoadFile; _fileLoadPath = MainBundleInfo.GetCacheLoadPath(); } else { throw new System.NotImplementedException(MainBundleInfo.LoadMode.ToString()); } } // 1. 从服务器下载 if (_steps == ESteps.Download) { int failedTryAgain = int.MaxValue; _downloader = DownloadSystem.BeginDownload(MainBundleInfo, failedTryAgain); _steps = ESteps.CheckDownload; } // 2. 检测服务器下载结果 if (_steps == ESteps.CheckDownload) { if (_downloader.IsDone() == false) { return; } if (_downloader.HasError()) { _steps = ESteps.Done; Status = EStatus.Failed; LastError = _downloader.GetLastError(); } else { _steps = ESteps.LoadFile; } } // 3. 加载AssetBundle if (_steps == ESteps.LoadFile) { #if UNITY_EDITOR // 注意:Unity2017.4编辑器模式下,如果AssetBundle文件不存在会导致编辑器崩溃,这里做了预判。 if (System.IO.File.Exists(_fileLoadPath) == false) { _steps = ESteps.Done; Status = EStatus.Failed; LastError = $"Not found assetBundle file : {_fileLoadPath}"; YooLogger.Error(LastError); return; } #endif // Load assetBundle file if (MainBundleInfo.IsEncrypted) { if (AssetSystem.DecryptionServices == null) { throw new Exception($"{nameof(AssetBundleFileLoader)} need {nameof(IDecryptionServices)} : {MainBundleInfo.BundleName}"); } ulong offset = AssetSystem.DecryptionServices.GetFileOffset(); if (_isWaitForAsyncComplete) { CacheBundle = AssetBundle.LoadFromFile(_fileLoadPath, 0, offset); } else { _cacheRequest = AssetBundle.LoadFromFileAsync(_fileLoadPath, 0, offset); } } else { if (_isWaitForAsyncComplete) { CacheBundle = AssetBundle.LoadFromFile(_fileLoadPath); } else { _cacheRequest = AssetBundle.LoadFromFileAsync(_fileLoadPath); } } _steps = ESteps.CheckFile; } // 4. 检测AssetBundle加载结果 if (_steps == ESteps.CheckFile) { if (_cacheRequest != null) { if (_isWaitForAsyncComplete) { // 强制挂起主线程(注意:该操作会很耗时) YooLogger.Warning("Suspend the main thread to load unity bundle."); CacheBundle = _cacheRequest.assetBundle; } else { if (_cacheRequest.isDone == false) { return; } CacheBundle = _cacheRequest.assetBundle; } } // Check error if (CacheBundle == null) { _steps = ESteps.Done; Status = EStatus.Failed; LastError = $"Failed to load assetBundle : {MainBundleInfo.BundleName}"; YooLogger.Error(LastError); } else { _steps = ESteps.Done; Status = EStatus.Succeed; } } }