NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/HotUpdate/GameLauncher.cs

255 lines
9.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.Collections;
using System.Collections.Generic;
using PhxhSDK.AOT;
using PhxhSDK.AOT.SimpleLoader;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.SceneManagement;
public class GameLauncher : MonoBehaviour
{
[Serializable]
private class DownloadContent
{
public List<string> catalogs = new();
}
const string START_SCENE_NAME = "Assets/Scenes/StartScene.unity";
//记录在playerPres里的需要下载的catalogs的ID
const string DOWNLOAD_CATALOGS_ID = "DownloadCatalogs";
//最大能容忍的下载卡住时长,一旦超过则重新开始下载
// private const float DOWNLOAD_STUCK_TIME_MAX = 10;
private Coroutine _launchCoroutine;
private HybridCLRHelper _hybridCLRHelper;
//version update
private AsyncOperationHandle _downloadOP;
private UI_VersionUpdate _versionUpdateUI;
private Type _versionUpdaterType;
// private float _downloadProgress;
// private float _downloadStuckTime;
private List<object> _KeysNeedToDownload = new();
//此对象里保存了需要下载的catalog每次获取新的catalog会将此对象保存到手机上如果在下载的过程中关闭了游戏下次打开还能拿到catalog继续下载
private DownloadContent _downloadContent = new();
private bool HasContentToDownload => _downloadContent != null && _downloadContent.catalogs != null &&
_downloadContent.catalogs.Count > 0;
public bool enableHotUpdate = true;
private void Start()
{
_launchCoroutine = StartCoroutine(Launch());
}
private void OnDestroy()
{
StopCoroutine(_launchCoroutine);
_launchCoroutine = null;
}
private IEnumerator Launch()
{
#if UNITY_EDITOR
enableHotUpdate = false;
#endif
#if USE_YOO
yield return YooAssetHelper.Init();
#endif
Debug.Log($"Launch Game! enableHotUpdate:{enableHotUpdate}");
yield return VersionCheck();
if (HasContentToDownload)
yield return VersionUpdate();
if (enableHotUpdate)
{
Debug.Log("需要热更新,开始加载程序集");
_hybridCLRHelper = new HybridCLRHelper();
_hybridCLRHelper.SetDllList(AOTGenericReferences.PatchedAOTAssemblyList);
#if USE_YOO
_hybridCLRHelper.RegistLoader(new SimpleLoader_YooAsset());
#else
_hybridCLRHelper.RegistLoader(new SimpleLoader_Addressables());
#endif
yield return _hybridCLRHelper.LoadAssemblies();
Debug.Log("加载程序集结束!");
}
yield return EnterGame();
}
private IEnumerator VersionCheck()
{
//todo 如果包体版本不一致则提示用户去app store重新下载
var checkUpdateOP = Addressables.CheckForCatalogUpdates(false);
Debug.Log("start checkUpdateOP");
yield return checkUpdateOP;
if (checkUpdateOP.Status == AsyncOperationStatus.Succeeded)
{
_downloadContent.catalogs = checkUpdateOP.Result;
if (HasContentToDownload)
{
Debug.Log("new version on server");
//如果服务器上的catalog和本地不一致则覆盖上一次需要下载的被内容
var jsonStr = JsonUtility.ToJson(_downloadContent);
PlayerPrefs.SetString(DOWNLOAD_CATALOGS_ID, jsonStr);
PlayerPrefs.Save();
}
else
{
if (PlayerPrefs.HasKey(DOWNLOAD_CATALOGS_ID))
{
Debug.Log("there are some contents remains from last downloading");
var jsonStr = PlayerPrefs.GetString(DOWNLOAD_CATALOGS_ID);
JsonUtility.FromJsonOverwrite(jsonStr, _downloadContent);
}
}
if (HasContentToDownload)
{
var updateCatalogOP = Addressables.UpdateCatalogs(_downloadContent.catalogs, false);
yield return updateCatalogOP;
if (updateCatalogOP.Status == AsyncOperationStatus.Succeeded)
{
_KeysNeedToDownload.Clear();
foreach (var resourceLocator in updateCatalogOP.Result)
{
_KeysNeedToDownload.AddRange(resourceLocator.Keys);
}
}
else
{
Debug.LogError($"Update catalog failed!exception:{updateCatalogOP.OperationException.Message}");
}
Addressables.Release(updateCatalogOP);
}
}
else
{
Debug.LogError($"CheckUpdate failed!exception:{checkUpdateOP.OperationException.Message}");
}
Addressables.Release(checkUpdateOP);
yield return SimpleLoader_Addressables.ReloadAddressableCatalog();
Debug.Log($"版本检查结束,是否有需要下载的内容:{HasContentToDownload}");
}
private IEnumerator VersionUpdate()
{
yield return OpenVersionUpdateUI();
yield return Download();
Debug.Log($"版本更新结束!");
}
//通过加载场景打开版本更新界面
private IEnumerator OpenVersionUpdateUI()
{
_versionUpdateUI = FindObjectOfType<UI_VersionUpdate>(true);
if (_versionUpdateUI == null)
{
Debug.LogError("cant find UI_VersionUpdate");
}
_versionUpdateUI.gameObject.SetActive(true);
return null;
}
//下载资源
private IEnumerator Download()
{
var downloadSizeOp = Addressables.GetDownloadSizeAsync((IEnumerable)_KeysNeedToDownload);
yield return downloadSizeOp;
Debug.Log($"download size:{downloadSizeOp.Result / (1024f * 1024f)}MB");
if (downloadSizeOp.Result > 0)
{
//_downloadStuckTime = 0;
Addressables.Release(downloadSizeOp);
// //下载经常在100%的时候卡住参考https://forum.unity.com/threads/addressables-1-14-2-downloaddependenciesasync-does-not-complete-randomly.966671/
// //倒数第二个回答
// var asyncLoadResources = Addressables.LoadResourceLocationsAsync((IEnumerable)_KeysNeedToDownload,
// Addressables.MergeMode.Union, null);
// IList<IResourceLocation> dependencyLoadList = new List<IResourceLocation>();
// yield return asyncLoadResources;
// foreach (var item in asyncLoadResources.Result)
// {
// dependencyLoadList.Add(item);
// }
//
// Addressables.Release(asyncLoadResources);
//
// _downloadOP =
// Addressables.DownloadDependenciesAsync(dependencyLoadList);
_downloadOP =
Addressables.DownloadDependenciesAsync((IEnumerable)_KeysNeedToDownload, Addressables.MergeMode.Union, false);
_versionUpdateUI.SetParams(_downloadOP);
// while (!_downloadOP.IsDone)
// {
// RefreshDownLoadStatus();
// if (!CheckIfNeedReDownload())
// yield return 0;
// else
// {
// //下载会经常卡在99%,此时还剩下很少的资源要下载,可以直接放弃下载,进入游戏
// //经过尝试上述方法行不通_downloadOp不能被终止如果直接release的话会导致后续逻辑报错
// Debug.LogError($"下载卡住超过时间上限,放弃下载!");
// yield return _downloadOP;
// }
// }
yield return _downloadOP;
if (_downloadOP.Status == AsyncOperationStatus.Succeeded)
Debug.Log($"下载完毕!");
else
Debug.LogError($"Download Update Content Failed! exception:{_downloadOP.OperationException.Message} \r\n {_downloadOP.OperationException.StackTrace}");
Addressables.Release(_downloadOP);
}
//清除需要下载的内容
Debug.Log($"delete key:{DOWNLOAD_CATALOGS_ID}");
PlayerPrefs.DeleteKey(DOWNLOAD_CATALOGS_ID);
}
// private void RefreshDownLoadStatus()
// {
// var currDownloadProgress = _downloadOP.GetDownloadStatus().Percent;
// if (Math.Abs(currDownloadProgress - _downloadProgress) < float.Epsilon)
// _downloadStuckTime += Time.deltaTime;
// else
// _downloadStuckTime = 0;
// _downloadProgress = currDownloadProgress;
// //Debug.Log($"下载进度:{_downloadProgress} 下载卡顿时间:{_downloadStuckTime}");
// }
//
// private bool CheckIfNeedReDownload() => _downloadStuckTime >= DOWNLOAD_STUCK_TIME_MAX;
private IEnumerator EnterGame()
{
var op = Addressables.LoadSceneAsync(START_SCENE_NAME, LoadSceneMode.Single);
yield return op;
if (op.Status != AsyncOperationStatus.Succeeded)
{
Debug.LogError(
$"load scene failed,exception:{op.OperationException.Message} \r\n {op.OperationException.StackTrace}");
yield break;
}
}
}