using System.Collections; using System.Collections.Generic; using UnityEngine; namespace SFramework { enum Update_State { usInvaild, usStart, usShowUI, usHotfixLua, usGetResVersion, usCalcUpdateResInfo, usDownloadResource, usFinish, } public class SUpdateManager : MonoBehaviour { private Update_State _currentState; private GameObject _logicInstance; private SUIPanelUpdate _uiPanelUpdate; private SUIPanelTips _uiPanelTips; private SVersionInfo _localResVersion, _remoteResVersion; private int _willDownloadBytes; private List _willDownloadFileInfoList = new List(); void Awake() { _currentState = Update_State.usStart; Debug.Log("Application.dataPath -> " + Application.dataPath); Debug.Log("Application.streamingAssetsPath -> " + Application.streamingAssetsPath); Debug.Log("Application.persistentDataPath -> " + Application.persistentDataPath); _logicInstance = GameObject.Find("LogicInstance"); Debug.Assert(_logicInstance != null); } void Start() { _currentState = Update_State.usShowUI; ShowUpdateUI(); AddUIController(); #pragma warning disable 0162 _currentState = Update_State.usHotfixLua; if (!SFrameworkDef.isEnableHotfix) _currentState = Update_State.usFinish; #pragma warning restore TryUpdate(); } private void ShowUpdateUI() { // Add CanvasUI GameObject canvasUpdate = SResourceManager.LoadResource("prefabs/canvas_update.prefab") as GameObject; GameObject.Instantiate(canvasUpdate); } private void AddUIController() { // Add UIController _uiPanelUpdate = _logicInstance.AddComponent(); _uiPanelTips = _logicInstance.AddComponent(); } public void TryUpdate() { StartCoroutine(UpdateLogic()); } public void UpdateStateInfo(string stateInfo) { Debug.Log("SUpdateManager -> " + stateInfo); _uiPanelUpdate.SetUpdateInfo(stateInfo); } IEnumerator UpdateLogic() { yield return null; switch (_currentState) { case Update_State.usHotfixLua: StartCoroutine(TryHotfixLuaLogic()); break; case Update_State.usGetResVersion: StartCoroutine(TryGetResVersionLogic()); break; case Update_State.usCalcUpdateResInfo: StartCoroutine(TryCalcUpdateResInfoLogic()); break; case Update_State.usDownloadResource: StartCoroutine(TryDownloadResource()); break; case Update_State.usFinish: StartCoroutine(TryFinishLogic()); break; default: Debug.Assert(false, "Update_State Error -> " + _currentState.ToString()); break; } yield return new WaitForSeconds(1.0f); // string resourceVersionURL = SFrameworkDef.resourceVersionUrl; // Step 3 : Switch To Start Scene. } IEnumerator TryHotfixLuaLogic() { // Step 1 : Try Hotfix. yield return null; UpdateStateInfo("Communication With Server ..."); yield return new WaitForSeconds(1.0f); string hotfixLuaUrl = SFrameworkDef.hotfixLuaUrl; UnityEngine.Networking.UnityWebRequest luaRequest = UnityEngine.Networking.UnityWebRequest.Get(hotfixLuaUrl); luaRequest.timeout = SFrameworkDef.httpRequestTimeoutTime; yield return luaRequest.SendWebRequest(); //if (luaRequest.isNetworkError || luaRequest.isHttpError) if (luaRequest.result == UnityEngine.Networking.UnityWebRequest.Result.ConnectionError || luaRequest.result == UnityEngine.Networking.UnityWebRequest.Result.ProtocolError) { Debug.LogError("SUpdateManager -> UpdateLogic luaRequest Error -> " + luaRequest.error); UpdateStateInfo("Communication With Server ... Error: " + luaRequest.error); // show tips and notice try again. _uiPanelTips.ShowTips( "Connect Failed", "Connection To Server Failed!\nPlease Check Your Network State.\nClick Yes Try Again. Click No Exit Game.", delegate(){ Debug.Log("SUpdateManager -> Click Tips Yes -> TryUpdate Again!"); TryUpdate(); }, delegate(){ Debug.Log("SUpdateManager -> Click Tips No -> Exit Game!"); Application.Quit(); } ); yield break; } string luaCode = luaRequest.downloadHandler.text; SLuaEnv.Instance.DoString(luaCode); UpdateStateInfo("Communication With Server ... Success"); _currentState = Update_State.usGetResVersion; TryUpdate(); } IEnumerator TryGetResVersionLogic() { // Step 2 : Try Get Res Version Info And Check IsNeed Update Resource. yield return null; UpdateStateInfo("Commuication With Resource Server ..."); yield return new WaitForSeconds(1.0f); string platformName = SPlatformInfo.GetBuildPlatformName(); string resVersionUrl = SFrameworkDef.resourceVersionUrlBase + platformName + "/" + SFrameworkDef.resourceVersionName; UnityEngine.Networking.UnityWebRequest resVersionRequest = UnityEngine.Networking.UnityWebRequest.Get(resVersionUrl); resVersionRequest.timeout = SFrameworkDef.httpRequestTimeoutTime; yield return resVersionRequest.SendWebRequest(); if (resVersionRequest.result == UnityEngine.Networking.UnityWebRequest.Result.ConnectionError || resVersionRequest.result == UnityEngine.Networking.UnityWebRequest.Result.ProtocolError) { Debug.LogError("SUpdateManager -> UpdateLogic resVersionRequest Error -> " + resVersionRequest.error); UpdateStateInfo("Communication With Resource Server ... Error: " + resVersionRequest.error); // show tips and notice try again. _uiPanelTips.ShowTips( "Connect Failed", "Connection To Resrouce Server Failed!\nPlease Check Your Network State.\nClick Yes Try Again. Click No Exit Game.", delegate() { Debug.Log("SUpdateManager -> Click Tips Yes -> Try Again!"); TryUpdate(); }, delegate() { Debug.Log("SUpdateManager -> Click Tips No -> Exit Game!"); Application.Quit(); } ); yield break; } // get version.json success start to calc download files info. string versionJson = resVersionRequest.downloadHandler.text; Debug.Log("remoteVersionJson -> " + versionJson); yield return new WaitForSeconds(1.0f); SVersionInfo remoteVersion = LitJson.JsonMapper.ToObject(versionJson); // Debug.Log("Remote Version -> " + remoteVersionInfo.version); SVersionInfo localVersion = SResourceManager.GetLocalVersionInfo(); // Debug.Log("Local Version -> " + localVersionInfo.version); UpdateStateInfo(string.Format("Remote Version: {0} Local Version: {1}", remoteVersion.version, localVersion.version)); yield return new WaitForSeconds(1.0f); _localResVersion = localVersion; _remoteResVersion = remoteVersion; yield return new WaitForSeconds(1.0f); UpdateStateInfo("Commuication With Resource Server ... Success"); _currentState = Update_State.usCalcUpdateResInfo; if (localVersion.version == remoteVersion.version) { // No need to update resource. _currentState = Update_State.usFinish; } // Debug.Log("currentState -> " + currentState.ToString()); TryUpdate(); } IEnumerator TryCalcUpdateResInfoLogic() { // Step 3: Try Update Resource By LocalVersionInfo And RemoteVersionInfo. yield return null; UpdateStateInfo("Prepare Calc Update Resource ..."); // Get Update File Count And File Total Size And Update FileInfoList. Debug.Assert(_localResVersion != null, "TryUpdateResourceLogic -> localResVersion = null"); Debug.Assert(_remoteResVersion != null, "TryUpdateResourceLogic -> remoteResVersion = null"); Debug.Assert(_localResVersion.version != _remoteResVersion.version, "TryUpdateResourceLogic -> LVersion == RVersion"); foreach (SFileInfo oneFileInfo in _remoteResVersion.fileInfo) { SFileInfo localFileInfo = _localResVersion.fileInfo.Find(target => { if (target.fileName == oneFileInfo.fileName) return true; else return false; } ); // File Existed And Don't Need Update. if (localFileInfo != null && localFileInfo.hashInfo == oneFileInfo.hashInfo) continue; // File Is Not Existed Or Need Update. _willDownloadBytes += oneFileInfo.fileSize; _willDownloadFileInfoList.Add(oneFileInfo); } UpdateStateInfo("Prepare Calc Update Resource ... Success"); // Show Tips For Player. // If Choose No Exit Game. // If Choose Yes Start Update Resource. _uiPanelTips.ShowTips( "UpdateInfo", string.Format( "Found new version:{0} ...\nFile Count:{1} FileSize:{2}", _remoteResVersion.version, _willDownloadFileInfoList.Count, System.Math.Round(_willDownloadBytes / 1024f / 1024f, 2) + "MB" ), delegate () { Debug.Log("SUpdateManager -> Click Tips Yes -> Start Download Logic"); _currentState = Update_State.usDownloadResource; TryUpdate(); }, delegate () { Debug.Log("SUpdateManager -> Click Tips No -> Exit Game"); Application.Quit(); } ); } IEnumerator TryDownloadResource() { // UnityWebRequest.GetAssetBundle(string url, int version, uint crc) // If crc is not zero, engine will compare crc. // UnityEngine.Networking.UnityWebRequest.GetAssetBundle("", 0, 0); yield return null; UpdateStateInfo("Prepare To Clean Local Resources ..."); yield return new WaitForSeconds(1.0f); // Download Resource Logic Start: // Step 1: Try To Delete All Local File(PersistentPath) That Need Update. int cleanedCount = 1; int fileTotalCount = _willDownloadFileInfoList.Count; foreach (SFileInfo oneFileInfo in _willDownloadFileInfoList) { SResourceManager.TryDeleteAssetBundle(oneFileInfo.fileName); UpdateStateInfo(string.Format( "Clean Local Files({0}/{1}) -> {2}", cleanedCount, fileTotalCount, oneFileInfo.fileName )); _uiPanelUpdate.SetProgressPercent(cleanedCount * 1.0f / fileTotalCount); cleanedCount++; yield return new WaitForSeconds(1.0f); } UpdateStateInfo("Clean All Local Resources ... Success"); yield return new WaitForSeconds(1.0f); // Step 2: Download Each File One By One And Write It On Right Path. UpdateStateInfo("Prepare To Download Remote Resources ..."); float downloadStartTime = UnityEngine.Time.realtimeSinceStartup; float downloadedBytes = 0.0f; string downloadSpeed = ""; foreach (SFileInfo oneFileInfo in _willDownloadFileInfoList) { float baseDownloadedBytes = downloadedBytes; string platformName = SPlatformInfo.GetBuildPlatformName(); string downloadLink = SFrameworkDef.resourceVersionUrlBase + platformName + "/" + oneFileInfo.fileName; UnityEngine.Networking.UnityWebRequest resDownloadRequest = // UnityEngine.Networking.UnityWebRequest.GetAssetBundle(downloadLink, (uint)remoteResVersion.version, 0); UnityEngine.Networking.UnityWebRequest.Get(downloadLink); float downloadPercent = 0.0f; _uiPanelUpdate.SetProgressPercent(downloadPercent); resDownloadRequest.SendWebRequest(); while (!resDownloadRequest.isDone) { downloadPercent = resDownloadRequest.downloadProgress * 100.0f; if (downloadPercent < 0) downloadPercent = 0; System.Math.Round(downloadPercent, 2); float fileDownloadBytes = baseDownloadedBytes + resDownloadRequest.downloadedBytes; downloadSpeed = SToolFunction.GetDownloadSpeed(fileDownloadBytes, UnityEngine.Time.realtimeSinceStartup - downloadStartTime); UpdateStateInfo(string.Format("Downloading: {0} From {1} \nPercent: {2} Speed:{3}", oneFileInfo.fileName, downloadLink, downloadPercent, downloadSpeed )); _uiPanelUpdate.SetProgressPercent(downloadPercent); yield return null; } _uiPanelUpdate.SetProgressPercent(1.0f); downloadedBytes += resDownloadRequest.downloadedBytes; downloadSpeed = SToolFunction.GetDownloadSpeed(downloadedBytes, UnityEngine.Time.realtimeSinceStartup - downloadStartTime); UpdateStateInfo(string.Format("Downloading: {0} \nPercent: {1} Speed:{2} Success", oneFileInfo.fileName, downloadPercent, downloadSpeed)); yield return new WaitForSeconds(1.0f); SResourceManager.SaveAssetBundle(oneFileInfo.fileName, resDownloadRequest.downloadHandler.data); UpdateStateInfo(string.Format("Download And Save {0} Success", oneFileInfo.fileName)); yield return new WaitForSeconds(1.0f); } downloadSpeed = SToolFunction.GetDownloadSpeed(downloadedBytes, UnityEngine.Time.realtimeSinceStartup - downloadStartTime); UpdateStateInfo("All Remote Resource Download Compelete ... Speed:" + downloadSpeed); // Step 3: Try Write version.json(Remote Version) To PersistentPath. SResourceManager.SaveRemoteVersion(_remoteResVersion); // Step 4: Change currentState And Call TryUpdate(). UpdateStateInfo("All Files Download Finish ..."); yield return new WaitForSeconds(1.0f); _currentState = Update_State.usFinish; TryUpdate(); } IEnumerator TryFinishLogic() { // Step 4: Try To Switch Scene To Start.unity. yield return null; UpdateStateInfo("All Data Updated ... Success"); yield return new WaitForSeconds(1.0f); yield return new WaitForSeconds(1.0f); SResourceManager.LoadResource("scenes/start.unity"); UnityEngine.SceneManagement.SceneManager.LoadScene("Start"); } } }