SUpdateManager.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. namespace SFramework
  5. {
  6. enum Update_State {
  7. usInvaild,
  8. usStart,
  9. usShowUI,
  10. usHotfixLua,
  11. usGetResVersion,
  12. usCalcUpdateResInfo,
  13. usDownloadResource,
  14. usFinish,
  15. }
  16. public class SUpdateManager : MonoBehaviour
  17. {
  18. private Update_State _currentState;
  19. private GameObject _logicInstance;
  20. private SUIPanelUpdate _uiPanelUpdate;
  21. private SUIPanelTips _uiPanelTips;
  22. private SVersionInfo _localResVersion, _remoteResVersion;
  23. private int _willDownloadBytes;
  24. private List<SFileInfo> _willDownloadFileInfoList = new List<SFileInfo>();
  25. void Awake()
  26. {
  27. _currentState = Update_State.usStart;
  28. Debug.Log("Application.dataPath -> " + Application.dataPath);
  29. Debug.Log("Application.streamingAssetsPath -> " + Application.streamingAssetsPath);
  30. Debug.Log("Application.persistentDataPath -> " + Application.persistentDataPath);
  31. _logicInstance = GameObject.Find("LogicInstance");
  32. Debug.Assert(_logicInstance != null);
  33. }
  34. void Start()
  35. {
  36. _currentState = Update_State.usShowUI;
  37. ShowUpdateUI();
  38. AddUIController();
  39. #pragma warning disable 0162
  40. _currentState = Update_State.usHotfixLua;
  41. if (!SFrameworkDef.isEnableHotfix) _currentState = Update_State.usFinish;
  42. #pragma warning restore
  43. TryUpdate();
  44. }
  45. private void ShowUpdateUI()
  46. {
  47. // Add CanvasUI
  48. GameObject canvasUpdate = SResourceManager.LoadResource("prefabs/canvas_update.prefab") as GameObject;
  49. GameObject.Instantiate(canvasUpdate);
  50. }
  51. private void AddUIController()
  52. {
  53. // Add UIController
  54. _uiPanelUpdate = _logicInstance.AddComponent<SUIPanelUpdate>();
  55. _uiPanelTips = _logicInstance.AddComponent<SUIPanelTips>();
  56. }
  57. public void TryUpdate()
  58. {
  59. StartCoroutine(UpdateLogic());
  60. }
  61. public void UpdateStateInfo(string stateInfo)
  62. {
  63. Debug.Log("SUpdateManager -> " + stateInfo);
  64. _uiPanelUpdate.SetUpdateInfo(stateInfo);
  65. }
  66. IEnumerator UpdateLogic()
  67. {
  68. yield return null;
  69. switch (_currentState)
  70. {
  71. case Update_State.usHotfixLua:
  72. StartCoroutine(TryHotfixLuaLogic());
  73. break;
  74. case Update_State.usGetResVersion:
  75. StartCoroutine(TryGetResVersionLogic());
  76. break;
  77. case Update_State.usCalcUpdateResInfo:
  78. StartCoroutine(TryCalcUpdateResInfoLogic());
  79. break;
  80. case Update_State.usDownloadResource:
  81. StartCoroutine(TryDownloadResource());
  82. break;
  83. case Update_State.usFinish:
  84. StartCoroutine(TryFinishLogic());
  85. break;
  86. default:
  87. Debug.Assert(false, "Update_State Error -> " + _currentState.ToString());
  88. break;
  89. }
  90. yield return new WaitForSeconds(1.0f);
  91. // string resourceVersionURL = SFrameworkDef.resourceVersionUrl;
  92. // Step 3 : Switch To Start Scene.
  93. }
  94. IEnumerator TryHotfixLuaLogic()
  95. {
  96. // Step 1 : Try Hotfix.
  97. yield return null;
  98. UpdateStateInfo("Communication With Server ...");
  99. yield return new WaitForSeconds(1.0f);
  100. string hotfixLuaUrl = SFrameworkDef.hotfixLuaUrl;
  101. UnityEngine.Networking.UnityWebRequest luaRequest =
  102. UnityEngine.Networking.UnityWebRequest.Get(hotfixLuaUrl);
  103. luaRequest.timeout = SFrameworkDef.httpRequestTimeoutTime;
  104. yield return luaRequest.SendWebRequest();
  105. if (luaRequest.isNetworkError || luaRequest.isHttpError)
  106. // for 2020
  107. //if (luaRequest.result == UnityEngine.Networking.UnityWebRequest.Result.ConnectionError || luaRequest.result == UnityEngine.Networking.UnityWebRequest.Result.ProtocolError)
  108. {
  109. Debug.LogError("SUpdateManager -> UpdateLogic luaRequest Error -> " + luaRequest.error);
  110. UpdateStateInfo("Communication With Server ... Error: " + luaRequest.error);
  111. // show tips and notice try again.
  112. _uiPanelTips.ShowTips(
  113. "Connect Failed",
  114. "Connection To Server Failed!\nPlease Check Your Network State.\nClick Yes Try Again. Click No Exit Game.",
  115. delegate(){
  116. Debug.Log("SUpdateManager -> Click Tips Yes -> TryUpdate Again!");
  117. TryUpdate();
  118. },
  119. delegate(){
  120. Debug.Log("SUpdateManager -> Click Tips No -> Exit Game!");
  121. Application.Quit();
  122. }
  123. );
  124. yield break;
  125. }
  126. string luaCode = luaRequest.downloadHandler.text;
  127. SLuaEnv.Instance.DoString(luaCode);
  128. UpdateStateInfo("Communication With Server ... Success");
  129. _currentState = Update_State.usGetResVersion;
  130. TryUpdate();
  131. }
  132. IEnumerator TryGetResVersionLogic()
  133. {
  134. // Step 2 : Try Get Res Version Info And Check IsNeed Update Resource.
  135. yield return null;
  136. UpdateStateInfo("Commuication With Resource Server ...");
  137. yield return new WaitForSeconds(1.0f);
  138. string platformName = SPlatformInfo.GetBuildPlatformName();
  139. string resVersionUrl = SFrameworkDef.resourceVersionUrlBase + platformName + "/" + SFrameworkDef.resourceVersionName;
  140. UnityEngine.Networking.UnityWebRequest resVersionRequest =
  141. UnityEngine.Networking.UnityWebRequest.Get(resVersionUrl);
  142. resVersionRequest.timeout = SFrameworkDef.httpRequestTimeoutTime;
  143. yield return resVersionRequest.SendWebRequest();
  144. if (resVersionRequest.isNetworkError || resVersionRequest.isHttpError)
  145. // for 2020
  146. //if (resVersionRequest.result == UnityEngine.Networking.UnityWebRequest.Result.ConnectionError || resVersionRequest.result == UnityEngine.Networking.UnityWebRequest.Result.ProtocolError)
  147. {
  148. Debug.LogError("SUpdateManager -> UpdateLogic resVersionRequest Error -> " + resVersionRequest.error);
  149. UpdateStateInfo("Communication With Resource Server ... Error: " + resVersionRequest.error);
  150. // show tips and notice try again.
  151. _uiPanelTips.ShowTips(
  152. "Connect Failed",
  153. "Connection To Resrouce Server Failed!\nPlease Check Your Network State.\nClick Yes Try Again. Click No Exit Game.",
  154. delegate() {
  155. Debug.Log("SUpdateManager -> Click Tips Yes -> Try Again!");
  156. TryUpdate();
  157. },
  158. delegate() {
  159. Debug.Log("SUpdateManager -> Click Tips No -> Exit Game!");
  160. Application.Quit();
  161. }
  162. );
  163. yield break;
  164. }
  165. // get version.json success start to calc download files info.
  166. string versionJson = resVersionRequest.downloadHandler.text;
  167. Debug.Log("remoteVersionJson -> " + versionJson);
  168. yield return new WaitForSeconds(1.0f);
  169. SVersionInfo remoteVersion = LitJson.JsonMapper.ToObject<SVersionInfo>(versionJson);
  170. // Debug.Log("Remote Version -> " + remoteVersionInfo.version);
  171. SVersionInfo localVersion = SResourceManager.GetLocalVersionInfo();
  172. // Debug.Log("Local Version -> " + localVersionInfo.version);
  173. UpdateStateInfo(string.Format("Remote Version: {0} Local Version: {1}", remoteVersion.version, localVersion.version));
  174. yield return new WaitForSeconds(1.0f);
  175. _localResVersion = localVersion;
  176. _remoteResVersion = remoteVersion;
  177. yield return new WaitForSeconds(1.0f);
  178. UpdateStateInfo("Commuication With Resource Server ... Success");
  179. _currentState = Update_State.usCalcUpdateResInfo;
  180. if (localVersion.version == remoteVersion.version)
  181. {
  182. // No need to update resource.
  183. _currentState = Update_State.usFinish;
  184. }
  185. // Debug.Log("currentState -> " + currentState.ToString());
  186. TryUpdate();
  187. }
  188. IEnumerator TryCalcUpdateResInfoLogic()
  189. {
  190. // Step 3: Try Update Resource By LocalVersionInfo And RemoteVersionInfo.
  191. yield return null;
  192. UpdateStateInfo("Prepare Calc Update Resource ...");
  193. // Get Update File Count And File Total Size And Update FileInfoList.
  194. Debug.Assert(_localResVersion != null, "TryUpdateResourceLogic -> localResVersion = null");
  195. Debug.Assert(_remoteResVersion != null, "TryUpdateResourceLogic -> remoteResVersion = null");
  196. Debug.Assert(_localResVersion.version != _remoteResVersion.version, "TryUpdateResourceLogic -> LVersion == RVersion");
  197. foreach (SFileInfo oneFileInfo in _remoteResVersion.fileInfo)
  198. {
  199. SFileInfo localFileInfo = _localResVersion.fileInfo.Find(target =>
  200. {
  201. if (target.fileName == oneFileInfo.fileName)
  202. return true;
  203. else
  204. return false;
  205. }
  206. );
  207. // File Existed And Don't Need Update.
  208. if (localFileInfo != null && localFileInfo.hashInfo == oneFileInfo.hashInfo)
  209. continue;
  210. // File Is Not Existed Or Need Update.
  211. _willDownloadBytes += oneFileInfo.fileSize;
  212. _willDownloadFileInfoList.Add(oneFileInfo);
  213. }
  214. UpdateStateInfo("Prepare Calc Update Resource ... Success");
  215. // Show Tips For Player.
  216. // If Choose No Exit Game.
  217. // If Choose Yes Start Update Resource.
  218. _uiPanelTips.ShowTips(
  219. "UpdateInfo",
  220. string.Format(
  221. "Found new version:{0} ...\nFile Count:{1} FileSize:{2}",
  222. _remoteResVersion.version, _willDownloadFileInfoList.Count,
  223. System.Math.Round(_willDownloadBytes / 1024f / 1024f, 2) + "MB"
  224. ),
  225. delegate () {
  226. Debug.Log("SUpdateManager -> Click Tips Yes -> Start Download Logic");
  227. _currentState = Update_State.usDownloadResource;
  228. TryUpdate();
  229. },
  230. delegate () {
  231. Debug.Log("SUpdateManager -> Click Tips No -> Exit Game");
  232. Application.Quit();
  233. }
  234. );
  235. }
  236. IEnumerator TryDownloadResource()
  237. {
  238. // UnityWebRequest.GetAssetBundle(string url, int version, uint crc)
  239. // If crc is not zero, engine will compare crc.
  240. // UnityEngine.Networking.UnityWebRequest.GetAssetBundle("", 0, 0);
  241. yield return null;
  242. UpdateStateInfo("Prepare To Clean Local Resources ...");
  243. yield return new WaitForSeconds(1.0f);
  244. // Download Resource Logic Start:
  245. // Step 1: Try To Delete All Local File(PersistentPath) That Need Update.
  246. int cleanedCount = 1;
  247. int fileTotalCount = _willDownloadFileInfoList.Count;
  248. foreach (SFileInfo oneFileInfo in _willDownloadFileInfoList)
  249. {
  250. SResourceManager.TryDeleteAssetBundle(oneFileInfo.fileName);
  251. UpdateStateInfo(string.Format(
  252. "Clean Local Files({0}/{1}) -> {2}", cleanedCount, fileTotalCount, oneFileInfo.fileName
  253. ));
  254. _uiPanelUpdate.SetProgressPercent(cleanedCount * 1.0f / fileTotalCount);
  255. cleanedCount++;
  256. yield return new WaitForSeconds(1.0f);
  257. }
  258. UpdateStateInfo("Clean All Local Resources ... Success");
  259. yield return new WaitForSeconds(1.0f);
  260. // Step 2: Download Each File One By One And Write It On Right Path.
  261. UpdateStateInfo("Prepare To Download Remote Resources ...");
  262. float downloadStartTime = UnityEngine.Time.realtimeSinceStartup;
  263. float downloadedBytes = 0.0f;
  264. string downloadSpeed = "";
  265. foreach (SFileInfo oneFileInfo in _willDownloadFileInfoList)
  266. {
  267. float baseDownloadedBytes = downloadedBytes;
  268. string platformName = SPlatformInfo.GetBuildPlatformName();
  269. string downloadLink = SFrameworkDef.resourceVersionUrlBase + platformName + "/" + oneFileInfo.fileName;
  270. UnityEngine.Networking.UnityWebRequest resDownloadRequest =
  271. // UnityEngine.Networking.UnityWebRequest.GetAssetBundle(downloadLink, (uint)remoteResVersion.version, 0);
  272. UnityEngine.Networking.UnityWebRequest.Get(downloadLink);
  273. float downloadPercent = 0.0f;
  274. _uiPanelUpdate.SetProgressPercent(downloadPercent);
  275. resDownloadRequest.SendWebRequest();
  276. while (!resDownloadRequest.isDone)
  277. {
  278. downloadPercent = resDownloadRequest.downloadProgress * 100.0f;
  279. if (downloadPercent < 0) downloadPercent = 0;
  280. System.Math.Round(downloadPercent, 2);
  281. float fileDownloadBytes = baseDownloadedBytes + resDownloadRequest.downloadedBytes;
  282. downloadSpeed = SToolFunction.GetDownloadSpeed(fileDownloadBytes, UnityEngine.Time.realtimeSinceStartup - downloadStartTime);
  283. UpdateStateInfo(string.Format("Downloading: {0} From {1} \nPercent: {2} Speed:{3}",
  284. oneFileInfo.fileName, downloadLink, downloadPercent, downloadSpeed
  285. ));
  286. _uiPanelUpdate.SetProgressPercent(downloadPercent);
  287. yield return null;
  288. }
  289. _uiPanelUpdate.SetProgressPercent(1.0f);
  290. downloadedBytes += resDownloadRequest.downloadedBytes;
  291. downloadSpeed = SToolFunction.GetDownloadSpeed(downloadedBytes, UnityEngine.Time.realtimeSinceStartup - downloadStartTime);
  292. UpdateStateInfo(string.Format("Downloading: {0} \nPercent: {1} Speed:{2} Success", oneFileInfo.fileName, downloadPercent, downloadSpeed));
  293. yield return new WaitForSeconds(1.0f);
  294. SResourceManager.SaveAssetBundle(oneFileInfo.fileName, resDownloadRequest.downloadHandler.data);
  295. UpdateStateInfo(string.Format("Download And Save {0} Success", oneFileInfo.fileName));
  296. yield return new WaitForSeconds(1.0f);
  297. }
  298. downloadSpeed = SToolFunction.GetDownloadSpeed(downloadedBytes, UnityEngine.Time.realtimeSinceStartup - downloadStartTime);
  299. UpdateStateInfo("All Remote Resource Download Compelete ... Speed:" + downloadSpeed);
  300. // Step 3: Try Write version.json(Remote Version) To PersistentPath.
  301. SResourceManager.SaveRemoteVersion(_remoteResVersion);
  302. // Step 4: Change currentState And Call TryUpdate().
  303. UpdateStateInfo("All Files Download Finish ...");
  304. yield return new WaitForSeconds(1.0f);
  305. _currentState = Update_State.usFinish;
  306. TryUpdate();
  307. }
  308. IEnumerator TryFinishLogic()
  309. {
  310. // Step 4: Try To Switch Scene To Start.unity.
  311. yield return null;
  312. UpdateStateInfo("All Data Updated ... Success");
  313. yield return new WaitForSeconds(1.0f);
  314. yield return new WaitForSeconds(1.0f);
  315. SResourceManager.LoadResource("scenes/start.unity");
  316. UnityEngine.SceneManagement.SceneManager.LoadScene("Start");
  317. }
  318. }
  319. }