using GFGGame.Launcher; using System.Collections; using UnityEngine; using YooAsset; using GFGGame.Launcher; namespace GFGGame { public class VersionController : SingletonMonoBase { public const string DefaultPackage = "GameLogic"; /// /// 包裹的版本信息 /// public string PackageVersion { set; get; } public void Init() { // 初始化资源系统 YooAssets.Initialize(); StartCoroutine(InitVersion()); } public IEnumerator InitVersion() { yield return InitDefaultPackage(); if(string.IsNullOrEmpty(LauncherConfig.manifest_v)) { yield return GetStaticVersion(DefaultPackage); } else { VersionController.Instance.PackageVersion = LauncherConfig.manifest_v; } yield return UpdateManifest(DefaultPackage); CreateDownloader(DefaultPackage); } private IEnumerator InitDefaultPackage() { // 创建默认的资源包 string packageName = DefaultPackage; var package = YooAssets.TryGetPackage(packageName); if (package == null) { package = YooAssets.CreatePackage(packageName); YooAssets.SetDefaultPackage(package); } var playMode = GameLauncher.Instance.PlayMode; #if !UNITY_EDITOR playMode = EPlayMode.HostPlayMode; #endif InitializationOperation initializationOperation = null; if (playMode == EPlayMode.EditorSimulateMode) { // 编辑器下的模拟模式 var createParameters = new EditorSimulateModeParameters(); createParameters.SimulateManifestFilePath = EditorSimulateModeHelper.SimulateBuild(packageName); initializationOperation = package.InitializeAsync(createParameters); } else if (playMode == EPlayMode.HostPlayMode) { // 联机运行模式 string defaultHostServer = GetHostServerURL(DefaultPackage); string fallbackHostServer = defaultHostServer; var createParameters = new HostPlayModeParameters(); //createParameters.DecryptionServices = new GameDecryptionServices(); createParameters.QueryServices = new GameQueryServices(); createParameters.RemoteServices = new RemoteServices(defaultHostServer, fallbackHostServer); initializationOperation = package.InitializeAsync(createParameters); } yield return initializationOperation; if (initializationOperation.Status != EOperationStatus.Succeed) { Debug.LogWarning($"{initializationOperation.Error}"); } } private IEnumerator GetStaticVersion(string packageName) { var package = YooAssets.GetPackage(packageName); var operation = package.UpdatePackageVersionAsync(); yield return operation; if (operation.Status == EOperationStatus.Succeed) { VersionController.Instance.PackageVersion = operation.PackageVersion; Debug.Log($"远端最新版本为: {operation.PackageVersion}"); } else { Debug.LogWarning(operation.Error); } } private IEnumerator UpdateManifest(string packageName) { bool savePackageVersion = true; var package = YooAssets.GetPackage(packageName); var operation = package.UpdatePackageManifestAsync(VersionController.Instance.PackageVersion, savePackageVersion); yield return operation; if (operation.Status != EOperationStatus.Succeed) { Debug.LogWarning(operation.Error); Alert.Show("更新版本信息失败,请检测网络链接后重试。") .SetLeftButton(true, "重试", (data) => { StartCoroutine(UpdateManifest(packageName)); }); } } private void CreateDownloader(string packageName) { int downloadingMaxNum = 10; int failedTryAgain = 3; ResourcePackage package = YooAssets.GetPackage(packageName); //ResourceDownloaderOperation downloaderOperation = package.CreateResourceDownloader(new string[] { "preload", "dynamic" }, downloadingMaxNum, failedTryAgain); ResourceDownloaderOperation downloaderOperation = package.CreateResourceDownloader(new string[] { "preload" }, downloadingMaxNum, failedTryAgain); if (downloaderOperation.TotalDownloadCount == 0) { LauncherController.OnVersionCompleted(); } else { //A total of 10 files were found that need to be downloaded Debug.Log($"Found total {downloaderOperation.TotalDownloadCount} files that need download !"); // 发现新更新文件后,挂起流程系统 // 注意:开发者需要在下载前检测磁盘空间不足 int totalDownloadCount = downloaderOperation.TotalDownloadCount; long totalDownloadBytes = downloaderOperation.TotalDownloadBytes; float sizeMB = totalDownloadBytes / 1048576f; sizeMB = Mathf.Clamp(sizeMB, 0.1f, float.MaxValue); string totalSizeMB = sizeMB.ToString("f1"); string message = $"游戏有新的内容,{packageName}需要更新{totalSizeMB}MB大小的内容"; Alert.Show(message) .SetLeftButton(true, "更新", (data) => { StartCoroutine(BeginDownload(downloaderOperation, packageName)); }); } } private IEnumerator BeginDownload(ResourceDownloaderOperation downloaderOperation, string packageName) { // 注册下载回调 downloaderOperation.OnDownloadErrorCallback = (fileName, error) => { Debug.LogError($"加载{fileName}失败 {error}"); }; downloaderOperation.OnDownloadProgressCallback = (totalDownloadCount, currentDownloadCount, totalDownloadSizeBytes, currentDownloadSizeBytes) => { string currentSizeMB = (currentDownloadSizeBytes / 1048576f).ToString("f1"); string totalSizeMB = (totalDownloadSizeBytes / 1048576f).ToString("f1"); var progress = (float)currentDownloadSizeBytes / totalDownloadSizeBytes; LauncherView.Instance.SetDesc($"正在下载资源,{currentDownloadCount}/{totalDownloadCount}", $"{currentSizeMB}MB/{totalSizeMB}MB", true); LauncherView.Instance.SetProgress((int)(progress * 100)); }; downloaderOperation.BeginDownload(); yield return downloaderOperation; // 检测下载结果 if (downloaderOperation.Status != EOperationStatus.Succeed) { Alert.Show("下载失败!请检查网络状态后重试。") .SetLeftButton(true, "重试", (data) => { StartCoroutine(BeginDownload(downloaderOperation, packageName)); }); yield break; } LauncherController.OnVersionCompleted(); } /// /// 获取资源服务器地址 /// private string GetHostServerURL(string packageName) { //string hostServerIP = "http://10.108.64.127"; string hostServerIP = LauncherConfig.CDN_ROOT; string platform = "PC"; #if UNITY_EDITOR if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.Android) platform = "Android"; else if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.iOS) platform = "IOS"; else if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.WebGL) platform = "WebGL"; #else if (Application.platform == RuntimePlatform.Android) platform = "Android"; else if (Application.platform == RuntimePlatform.IPhonePlayer) platform = "IOS"; else if (Application.platform == RuntimePlatform.WebGLPlayer) platform = "WebGL"; #endif return $"{hostServerIP}/{platform}/{packageName}/HostPlay"; } /// /// 远端资源地址查询服务类 /// 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}"; } } } }