VersionController.cs 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. using GFGGame.Launcher;
  2. using System.Collections;
  3. using UnityEngine;
  4. using YooAsset;
  5. namespace GFGGame
  6. {
  7. public class VersionController : SingletonMonoBase<VersionController>
  8. {
  9. public const string DefaultPackage = "GameLogic";
  10. /// <summary>
  11. /// 包裹的版本信息
  12. /// </summary>
  13. public string PackageVersion { set; get; }
  14. public void Init()
  15. {
  16. // 初始化资源系统
  17. YooAssets.Initialize();
  18. StartCoroutine(InitVersion());
  19. }
  20. public IEnumerator InitVersion()
  21. {
  22. yield return InitDefaultPackage();
  23. if(string.IsNullOrEmpty(LauncherConfig.manifest_v))
  24. {
  25. yield return GetStaticVersion(DefaultPackage);
  26. }
  27. else
  28. {
  29. VersionController.Instance.PackageVersion = LauncherConfig.manifest_v;
  30. }
  31. yield return UpdateManifest(DefaultPackage);
  32. CreateDownloader(DefaultPackage);
  33. }
  34. private IEnumerator InitDefaultPackage()
  35. {
  36. // 创建默认的资源包
  37. string packageName = DefaultPackage;
  38. var package = YooAssets.TryGetPackage(packageName);
  39. if (package == null)
  40. {
  41. package = YooAssets.CreatePackage(packageName);
  42. YooAssets.SetDefaultPackage(package);
  43. }
  44. var playMode = GameLauncher.Instance.PlayMode;
  45. #if !UNITY_EDITOR
  46. playMode = EPlayMode.HostPlayMode;
  47. #endif
  48. InitializationOperation initializationOperation = null;
  49. if (playMode == EPlayMode.EditorSimulateMode)
  50. {
  51. // 编辑器下的模拟模式
  52. var createParameters = new EditorSimulateModeParameters();
  53. createParameters.SimulateManifestFilePath = EditorSimulateModeHelper.SimulateBuild(packageName);
  54. initializationOperation = package.InitializeAsync(createParameters);
  55. }
  56. else if (playMode == EPlayMode.HostPlayMode)
  57. {
  58. // 联机运行模式
  59. string defaultHostServer = GetHostServerURL(DefaultPackage);
  60. string fallbackHostServer = defaultHostServer;
  61. var createParameters = new HostPlayModeParameters();
  62. //createParameters.DecryptionServices = new GameDecryptionServices();
  63. createParameters.QueryServices = new GameQueryServices();
  64. createParameters.RemoteServices = new RemoteServices(defaultHostServer, fallbackHostServer);
  65. initializationOperation = package.InitializeAsync(createParameters);
  66. }
  67. yield return initializationOperation;
  68. if (initializationOperation.Status != EOperationStatus.Succeed)
  69. {
  70. Debug.LogWarning($"{initializationOperation.Error}");
  71. }
  72. }
  73. private IEnumerator GetStaticVersion(string packageName)
  74. {
  75. var package = YooAssets.GetPackage(packageName);
  76. var operation = package.UpdatePackageVersionAsync();
  77. yield return operation;
  78. if (operation.Status == EOperationStatus.Succeed)
  79. {
  80. VersionController.Instance.PackageVersion = operation.PackageVersion;
  81. Debug.Log($"远端最新版本为: {operation.PackageVersion}");
  82. }
  83. else
  84. {
  85. Debug.LogWarning(operation.Error);
  86. }
  87. }
  88. private IEnumerator UpdateManifest(string packageName)
  89. {
  90. bool savePackageVersion = true;
  91. var package = YooAssets.GetPackage(packageName);
  92. var operation = package.UpdatePackageManifestAsync(VersionController.Instance.PackageVersion, savePackageVersion);
  93. yield return operation;
  94. if (operation.Status != EOperationStatus.Succeed)
  95. {
  96. Debug.LogWarning(operation.Error);
  97. Alert.Show("更新版本信息失败,请检测网络链接后重试。")
  98. .SetLeftButton(true, "重试", (data) => { StartCoroutine(UpdateManifest(packageName)); });
  99. }
  100. }
  101. private void CreateDownloader(string packageName)
  102. {
  103. int downloadingMaxNum = 10;
  104. int failedTryAgain = 3;
  105. ResourcePackage package = YooAssets.GetPackage(packageName);
  106. //ResourceDownloaderOperation downloaderOperation = package.CreateResourceDownloader(new string[] { "preload", "dynamic" }, downloadingMaxNum, failedTryAgain);
  107. ResourceDownloaderOperation downloaderOperation = package.CreateResourceDownloader(new string[] { "preload" }, downloadingMaxNum, failedTryAgain);
  108. if (downloaderOperation.TotalDownloadCount == 0)
  109. {
  110. LauncherController.OnVersionCompleted();
  111. }
  112. else
  113. {
  114. //A total of 10 files were found that need to be downloaded
  115. Debug.Log($"Found total {downloaderOperation.TotalDownloadCount} files that need download !");
  116. // 发现新更新文件后,挂起流程系统
  117. // 注意:开发者需要在下载前检测磁盘空间不足
  118. int totalDownloadCount = downloaderOperation.TotalDownloadCount;
  119. long totalDownloadBytes = downloaderOperation.TotalDownloadBytes;
  120. float sizeMB = totalDownloadBytes / 1048576f;
  121. sizeMB = Mathf.Clamp(sizeMB, 0.1f, float.MaxValue);
  122. if(sizeMB > LauncherConfig.promptSizeMB)
  123. {
  124. string totalSizeMB = sizeMB.ToString("f1");
  125. if(string.IsNullOrEmpty(LauncherConfig.updateResPrompt))
  126. {
  127. LauncherConfig.updateResPrompt = $"游戏有新的内容,需要更新{0}MB大小的资源";
  128. }
  129. string message = string.Format(LauncherConfig.updateResPrompt, totalSizeMB);
  130. Alert.Show(message)
  131. .SetLeftButton(true, "更新", (data) =>
  132. {
  133. StartCoroutine(BeginDownload(downloaderOperation, packageName));
  134. });
  135. }
  136. else
  137. {
  138. StartCoroutine(BeginDownload(downloaderOperation, packageName));
  139. }
  140. }
  141. }
  142. private IEnumerator BeginDownload(ResourceDownloaderOperation downloaderOperation, string packageName)
  143. {
  144. // 注册下载回调
  145. downloaderOperation.OnDownloadErrorCallback =
  146. (fileName, error) =>
  147. {
  148. Debug.LogError($"加载{fileName}失败 {error}");
  149. };
  150. downloaderOperation.OnDownloadProgressCallback =
  151. (totalDownloadCount, currentDownloadCount, totalDownloadSizeBytes, currentDownloadSizeBytes) =>
  152. {
  153. string currentSizeMB = (currentDownloadSizeBytes / 1048576f).ToString("f1");
  154. string totalSizeMB = (totalDownloadSizeBytes / 1048576f).ToString("f1");
  155. var progress = (float)currentDownloadSizeBytes / totalDownloadSizeBytes;
  156. LauncherView.Instance.SetDesc($"正在下载资源,{currentDownloadCount}/{totalDownloadCount}", $"{currentSizeMB}MB/{totalSizeMB}MB", true);
  157. LauncherView.Instance.SetProgress((int)(progress * 100));
  158. };
  159. downloaderOperation.BeginDownload();
  160. yield return downloaderOperation;
  161. // 检测下载结果
  162. if (downloaderOperation.Status != EOperationStatus.Succeed)
  163. {
  164. Alert.Show("下载失败!请检查网络状态后重试。")
  165. .SetLeftButton(true, "重试", (data) =>
  166. {
  167. StartCoroutine(BeginDownload(downloaderOperation, packageName));
  168. });
  169. yield break;
  170. }
  171. LauncherController.OnVersionCompleted();
  172. }
  173. /// <summary>
  174. /// 获取资源服务器地址
  175. /// </summary>
  176. private string GetHostServerURL(string packageName)
  177. {
  178. //LauncherConfig.CDN_ROOT = "http://10.108.64.127";
  179. string platform = "PC";
  180. #if UNITY_EDITOR
  181. if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.Android)
  182. platform = "Android";
  183. else if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.iOS)
  184. platform = "IOS";
  185. else if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.WebGL)
  186. platform = "WebGL";
  187. #else
  188. if (Application.platform == RuntimePlatform.Android)
  189. platform = "Android";
  190. else if (Application.platform == RuntimePlatform.IPhonePlayer)
  191. platform = "IOS";
  192. else if (Application.platform == RuntimePlatform.WebGLPlayer)
  193. platform = "WebGL";
  194. #endif
  195. return $"{LauncherConfig.CDN_ROOT}/{platform}/{packageName}/HostPlay";
  196. }
  197. /// <summary>
  198. /// 远端资源地址查询服务类
  199. /// </summary>
  200. private class RemoteServices : IRemoteServices
  201. {
  202. private readonly string _defaultHostServer;
  203. private readonly string _fallbackHostServer;
  204. public RemoteServices(string defaultHostServer, string fallbackHostServer)
  205. {
  206. _defaultHostServer = defaultHostServer;
  207. _fallbackHostServer = fallbackHostServer;
  208. }
  209. string IRemoteServices.GetRemoteMainURL(string fileName)
  210. {
  211. return $"{_defaultHostServer}/{fileName}";
  212. }
  213. string IRemoteServices.GetRemoteFallbackURL(string fileName)
  214. {
  215. return $"{_fallbackHostServer}/{fileName}";
  216. }
  217. }
  218. }
  219. }