using System; using System.Collections; using System.IO; using Cysharp.Threading.Tasks; using UnityEngine; using YooAsset; using ZFramework.Runtime; using ZGame; namespace HK { public class InitializePackage { /// /// 资源系统运行模式 /// private EPlayMode PlayMode = EPlayMode.EditorSimulateMode; private string PackageName = "DefaultPackage"; public InitializePackage(EPlayMode playMode, string packageName, string hostServerIP, string appVersion) { PlayMode = playMode; PackageName = packageName; this.hostServerIP = hostServerIP; this.appVersion = appVersion; } public async UniTask Start() { Debug.Log($"资源系统运行模式:{PlayMode}"); Application.targetFrameRate = 60; Application.runInBackground = true; // 游戏管理器 // GameManager.Instance.Behaviour = this; // // // 初始化事件系统 // UniEvent.Initalize(); // 初始化资源系统 YooAssets.Initialize(); // 加载更新页面 var go = Resources.Load("PatchWindow"); GameObject.Instantiate(go); #if ENABLE_WEBGL || PLATFORM_WEBGL YooAssets.SetCacheSystemDisableCacheOnWebGL(); #endif EventManager.Instance.Subscribe(UpdatePackageCallbackEventArgs.EventId, UpdatePackageCallbackEvent); // 开始补丁更新流程 // var operation = new PatchOperation("DefaultPackage", PlayMode); // YooAssets.StartOperation(operation); await InitPackage(); // 设置默认的资源包 var gamePackage = YooAssets.GetPackage("DefaultPackage"); YooAssets.SetDefaultPackage(gamePackage); // 切换到主页面场景 // SceneEventDefine.ChangeToHomeScene.SendEventMessage(); // YooAssets.LoadSceneSync(SceneName); Debug.Log("完成"); } private void UpdatePackageCallbackEvent(object sender, GameEventArgs e) { var args = e as UpdatePackageCallbackEventArgs; switch (args.callbackType) { case UpdatePackageCallbackType.再次初始化资源包: this.InitPackage().Forget(); break; case UpdatePackageCallbackType.开始下载网络文件: this.FsmDownloadPackageFiles().Forget(); break; case UpdatePackageCallbackType.再次更新静态版本: this.UpdatePackageVersion().Forget(); break; case UpdatePackageCallbackType.再次更新补丁清单: this.FsmUpdatePackageManifest().Forget(); break; case UpdatePackageCallbackType.再次下载网络文件: this.FsmDownloadPackageFiles().Forget(); break; default: throw new ArgumentOutOfRangeException(); } } #region FsmInitializePackage private async UniTask InitPackage() { // 创建资源包裹类 var package = YooAssets.TryGetPackage(PackageName); if (package == null) package = YooAssets.CreatePackage(PackageName); // 编辑器下的模拟模式 InitializationOperation initializationOperation = null; if (PlayMode == EPlayMode.EditorSimulateMode) { var buildResult = EditorSimulateModeHelper.SimulateBuild(PackageName); var packageRoot = buildResult.PackageRootDirectory; var createParameters = new EditorSimulateModeParameters(); createParameters.EditorFileSystemParameters = FileSystemParameters.CreateDefaultEditorFileSystemParameters(packageRoot); initializationOperation = package.InitializeAsync(createParameters); } // 单机运行模式 if (PlayMode == EPlayMode.OfflinePlayMode) { var createParameters = new OfflinePlayModeParameters(); createParameters.BuildinFileSystemParameters = FileSystemParameters.CreateDefaultBuildinFileSystemParameters(); initializationOperation = package.InitializeAsync(createParameters); } // 联机运行模式 if (PlayMode == EPlayMode.HostPlayMode) { string defaultHostServer = GetHostServerURL(); string fallbackHostServer = GetHostServerURL(); IRemoteServices remoteServices = new RemoteServices(defaultHostServer, fallbackHostServer); var createParameters = new HostPlayModeParameters(); createParameters.BuildinFileSystemParameters = FileSystemParameters.CreateDefaultBuildinFileSystemParameters(); createParameters.CacheFileSystemParameters = FileSystemParameters.CreateDefaultCacheFileSystemParameters(remoteServices); initializationOperation = package.InitializeAsync(createParameters); } // WebGL运行模式 if (PlayMode == EPlayMode.WebPlayMode) { #if UNITY_WEBGL && WEIXINMINIGAME && !UNITY_EDITOR var createParameters = new WebPlayModeParameters(); string defaultHostServer = GetHostServerURL(); string fallbackHostServer = GetHostServerURL(); string packageRoot = $"{WeChatWASM.WX.env.USER_DATA_PATH}/__GAME_FILE_CACHE"; //注意:如果有子目录,请修改此处! IRemoteServices remoteServices = new RemoteServices(defaultHostServer, fallbackHostServer); createParameters.WebServerFileSystemParameters = WechatFileSystemCreater.CreateFileSystemParameters(packageRoot, remoteServices); initializationOperation = package.InitializeAsync(createParameters); #else var createParameters = new WebPlayModeParameters(); createParameters.WebServerFileSystemParameters = FileSystemParameters.CreateDefaultWebServerFileSystemParameters(); initializationOperation = package.InitializeAsync(createParameters); #endif } await initializationOperation.Task; // 如果初始化失败弹出提示界面 if (initializationOperation.Status != EOperationStatus.Succeed) { Debug.LogWarning($"{initializationOperation.Error}"); // PatchEventDefine.InitializeFailed.SendEventMessage(); EventManager.Instance.FireNow(this, new InitializeFailedEventArgs()); } else { // _machine.ChangeState(); await UpdatePackageVersion(); } } string hostServerIP = "http://127.0.0.1"; string appVersion = "v1.0"; /// /// 获取资源服务器地址 /// private string GetHostServerURL() { //string hostServerIP = "http://10.0.2.2"; //安卓模拟器地址 // string hostServerIP = "http://127.0.0.1"; // string appVersion = "v1.0"; #if UNITY_EDITOR if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.Android) return $"{hostServerIP}/CDN/Android/{Application.productName}/{appVersion}"; else if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.iOS) return $"{hostServerIP}/CDN/IPhone/{Application.productName}/{appVersion}"; else if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.WebGL) return $"{hostServerIP}/CDN/WebGL/{Application.productName}/{appVersion}"; else return $"{hostServerIP}/CDN/PC/{Application.productName}/{appVersion}"; #else if (Application.platform == RuntimePlatform.Android) return $"{hostServerIP}/CDN/Android/{Application.productName}/{appVersion}"; else if (Application.platform == RuntimePlatform.IPhonePlayer) return $"{hostServerIP}/CDN/IPhone/{Application.productName}/{appVersion}"; else if (Application.platform == RuntimePlatform.WebGLPlayer) return $"{hostServerIP}/CDN/WebGL/{Application.productName}/{appVersion}"; else return $"{hostServerIP}/CDN/PC/{Application.productName}/{appVersion}"; #endif } /// /// 远端资源地址查询服务类 /// private class RemoteServices : IRemoteServices { private readonly string _defaultHostServer; private readonly string _fallbackHostServer; public RemoteServices(string defaultHostServer, string fallbackHostServer) { _defaultHostServer = defaultHostServer; _fallbackHostServer = fallbackHostServer; } string IRemoteServices.GetRemoteMainURL(string fileName) { return $"{_defaultHostServer}/{fileName}"; } string IRemoteServices.GetRemoteFallbackURL(string fileName) { return $"{_fallbackHostServer}/{fileName}"; } } #endregion #region FsmRequestPackageVersion private async UniTask UpdatePackageVersion() { var package = YooAssets.GetPackage(PackageName); var operation = package.RequestPackageVersionAsync(); await operation.Task; if (operation.Status != EOperationStatus.Succeed) { Debug.LogWarning(operation.Error); EventManager.Instance.FireNow(this, new PackageVersionUpdateFailedEventArgs()); } else { Debug.Log($"Request package version : {operation.PackageVersion}"); packageVersion = operation.PackageVersion; await FsmUpdatePackageManifest(); } } string packageVersion; #endregion #region FsmUpdatePackageManifest private async UniTask FsmUpdatePackageManifest() { var package = YooAssets.GetPackage(PackageName); var operation = package.UpdatePackageManifestAsync(packageVersion); await operation.Task; if (operation.Status != EOperationStatus.Succeed) { Debug.LogWarning(operation.Error); EventManager.Instance.FireNow(this, new PatchManifestUpdateFailedEventArgs()); return; } else { await FsmCreateDownloader(); } } #endregion #region FsmCreateDownloader private async UniTask FsmCreateDownloader() { await UniTask.Yield(); Log.Debug("创建资源下载器!"); CreateDownloader(); } ResourceDownloaderOperation downloader; void CreateDownloader() { var package = YooAssets.GetPackage(PackageName); int downloadingMaxNum = 10; int failedTryAgain = 3; downloader = package.CreateResourceDownloader(downloadingMaxNum, failedTryAgain); // _machine.SetBlackboardValue("Downloader", downloader); if (downloader.TotalDownloadCount == 0) { Debug.Log("Not found any download files !"); // _machine.ChangeState(); UniTask.Run(FsmStartGame); } else { // 发现新更新文件后,挂起流程系统 // 注意:开发者需要在下载前检测磁盘空间不足 int totalDownloadCount = downloader.TotalDownloadCount; long totalDownloadBytes = downloader.TotalDownloadBytes; EventManager.Instance.FireNow(this, new FoundUpdateFilesEventArgs(totalDownloadCount, totalDownloadBytes)); } } #endregion #region FsmDownloadPackageFiles private async UniTask FsmDownloadPackageFiles() { await UniTask.Yield(); Log.Debug("开始下载资源文件!"); downloader.DownloadErrorCallback = DownloadErrorCallback; downloader.DownloadUpdateCallback = DownloadProgressCallback; downloader.BeginDownload(); await downloader.Task; // 检测下载结果 if (downloader.Status != EOperationStatus.Succeed) return; await FsmDownloadPackageOver(); void DownloadErrorCallback(DownloadErrorData data) { Debug.Log($"下载补丁出错!{data.ErrorInfo}"); EventManager.Instance.FireNow(this, new WebFileDownloadFailedEventArgs(data.FileName, data.ErrorInfo)); } void DownloadProgressCallback(DownloadUpdateData data) { Debug.Log( $"下载进度:{data.CurrentDownloadCount}/{data.TotalDownloadCount} , {data.CurrentDownloadBytes}/{data.TotalDownloadBytes}!"); EventManager.Instance.FireNow(this, new DownloadProgressUpdateEventArgs(data.CurrentDownloadCount, data.TotalDownloadCount, data.CurrentDownloadBytes, data.TotalDownloadBytes)); } } #endregion #region FsmDownloadPackageOver private async UniTask FsmDownloadPackageOver() { await UniTask.Yield(); Log.Debug("资源文件下载完毕!"); await FsmClearCacheBundle(); } #endregion #region FsmClearCacheBundle private async UniTask FsmClearCacheBundle() { await UniTask.Yield(); Log.Debug("清理未使用的缓存文件!"); var package = YooAssets.GetPackage(PackageName); var operation = package.ClearCacheFilesAsync(EFileClearMode.ClearUnusedBundleFiles); operation.Completed += Operation_Completed; } private void Operation_Completed(YooAsset.AsyncOperationBase obj) { UniTask.Run(FsmStartGame); } #endregion #region FsmStartGame private async UniTask FsmStartGame() { await UniTask.Yield(); Log.Debug("开始游戏!"); } #endregion } }