VersionController.cs 9.7 KB

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