JJBB/Assets/Plugins/Script/AssetUpdate/AssetUpdateManager.cs

426 lines
14 KiB
C#
Raw Normal View History

2024-08-23 15:49:34 +08:00
// 在AssetBundleManager等资源管理器生成前预先处理资源问题的管理器
// 提前处理资源更新,服务器列表下载等一系列情况
// 注这个东西运作的时候没有AssetBundle没有Lua不要试图做任何相关操作。
2024-08-23 15:49:34 +08:00
using System.Collections.Generic;
using System.Reflection;
using AssetUpdate;
using Games.GlobeDefine;
using UnityEngine;
using UnityEngine.EventSystems;
using SceneHub = UnityEngine.SceneManagement.SceneManager;
public class AssetUpdateManager : MonoBehaviour
{
// 处理不同渠道的Php链接数据
private const string _channelConfig = "Channel.txt";
private IAssetAsyncAction _currentAction;
public static Assembly dllAssembly { get; private set; }
private static string _channel;
public static string channel
{
get { return _channel; }
private set { _channel = value; }
}
2024-08-23 15:49:34 +08:00
public static string assetVersionUri { get; private set; }
public static bool useResources
{
get { return _useResources; }
}
2024-08-23 15:49:34 +08:00
private static bool _useResources = true;
public AssetUpdateState state { get; private set; }
public AssetUpdateError error { get; private set; }
public static string assetUri { get; private set; }
public static int assetVersion { get; private set; }
public static string apkUri { get; private set; }
public static string apkVersion { get; private set; }
2024-08-23 15:49:34 +08:00
public List<AssetDependencyItem> downloadList { get; private set; }
public AssetDependencyInfo mainInfo { get; private set; }
2024-08-23 15:49:34 +08:00
public Dictionary<string, string> streamingPathInfo { get; private set; }
private const string currentVersionPref = "CurrentVersion";
2024-08-23 15:49:34 +08:00
public static int LoadCurrentVersion()
{
var currentVersion = PlayerPrefs.GetInt(currentVersionPref, default(int));
if (currentVersion <= 0)
{
var versionFile = Resources.Load<TextAsset>(AssetConst.currentVersionFile).text;
int version;
if (int.TryParse(versionFile, out version))
currentVersion = version;
}
2024-08-23 15:49:34 +08:00
return currentVersion;
}
private void SaveCurrentVersion()
{
PlayerPrefs.SetInt(currentVersionPref, assetVersion);
}
2024-08-23 15:49:34 +08:00
private void Awake()
{
Debug.Log("AssetUpdateManager Awake");
2024-08-23 15:49:34 +08:00
_useResources = false;
AssetUpdateDownloaderTick.CreateInstance();
if (!FirstSceneBg.instance)
FirstSceneBg.CreateInstance();
CreateEventSystem();
}
public static void CreateEventSystem()
{
if (!EventSystem.current)
{
var eventObj = new GameObject("EventSystem");
eventObj.AddComponent<EventSystem>();
eventObj.AddComponent<StandaloneInputModule>();
DontDestroyOnLoad(eventObj);
}
}
private void OnConfigLoad(WWW www)
{
var text = string.IsNullOrEmpty(www.error) ? www.text : string.Empty;
2024-08-23 15:49:34 +08:00
var channelError = false;
if (string.IsNullOrEmpty(text))
channelError = true;
else
{
var lines = AssetUtils.TextToLines(text);
if (lines.Length < 2)
channelError = true;
else
{
channel = lines[0].Trim();
2024-08-23 15:49:34 +08:00
assetVersionUri = lines[1].Trim();
if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(assetVersionUri))
channelError = true;
if (lines.Length > 2)
{
var extra = lines[2].Trim();
if (lines.Length > 2 && !string.IsNullOrEmpty(extra))
FirstSceneBg.instance.SetPublishText(extra);
}
}
}
2024-08-23 15:49:34 +08:00
if (channelError)
Debug.LogError("Unable to Parse Channel file! This is not recoverable!");
else
{
// 清理上次执行残留的rawJsonText
// 当前项目没有类似数据缓存库一样的类,暂时直接用静态传递
assetUri = string.Empty;
state = AssetUpdateState.GetUpdateInfo;
2024-08-23 15:49:34 +08:00
StartCurrentAction();
}
2024-08-23 15:49:34 +08:00
FirstSceneBg.instance.ShowGameVersion();
// 清理上次执行残留的rawJsonText
// 当前项目没有类似数据缓存库一样的类,暂时直接用静态传递
assetUri = string.Empty;
state = AssetUpdateState.GetUpdateInfo;
2024-08-23 15:49:34 +08:00
StartCurrentAction();
}
2024-08-23 15:49:34 +08:00
private void Start()
{
// 特别处理Android Resume时期的诡异情况该状况下AssetBundle未被清空但实际Bundle管理器已被析构
AssetBundle.UnloadAllAssetBundles(true);
Debug.Log("加载渠道文件" + _channelConfig);
2024-08-23 15:49:34 +08:00
AssetUpdateDownloaderTick.instance.LoadStreamingAsset(_channelConfig, OnConfigLoad);
}
private void OnDestroy()
{
// 即使AppQuit也需要处理OnDestroy否则会在编辑器中导致下载不中断
if (state != AssetUpdateState.Complete && _currentAction != null)
{
_currentAction.Dispose();
_currentAction = null;
}
}
private void StartCurrentAction()
{
switch (state)
{
case AssetUpdateState.GetUpdateInfo:
{
var httpAction = new HttpsGetAction(10f);
_currentAction = httpAction;
httpAction.Start();
}
break;
case AssetUpdateState.DownloadAssetList:
{
var assetListAction = new AssetVersionAction();
_currentAction = assetListAction;
assetListAction.Start(assetVersion, assetUri);
}
break;
case AssetUpdateState.CompareAssetList:
{
var assetCompareAction = new AssetCompareAction();
_currentAction = assetCompareAction;
assetCompareAction.Start(mainInfo);
}
break;
case AssetUpdateState.DownloadFile:
{
var downloadAction = new ProjectDownloadAction();
_currentAction = downloadAction;
downloadAction.Start(assetUri, downloadList);
}
break;
default:
{
Debug.LogError(string.Format("Unhandled state {0} in StartCurrentAction", state));
}
break;
}
}
private static T ConvertAction<T>(IAssetAsyncAction action) where T : class, IAssetAsyncAction
{
var result = action as T;
if (result == null)
Debug.LogError("Logic Error: current Action is not " + typeof(T));
return result;
}
public static JsonAssetInfo HandleHttpGetAction(HttpsGetAction httpAction)
{
JsonAssetInfo jsonAssetInfo = null;
if (httpAction != null)
{
if (httpAction.jsonData == null)
Debug.LogError("HttpsGetAction Error: failed to get json from server");
else
jsonAssetInfo = JsonAssetInfo.Create(httpAction.jsonData);
}
2024-08-23 15:49:34 +08:00
return jsonAssetInfo;
}
2024-08-23 15:49:34 +08:00
private void EndCurrentAction()
{
error = AssetUpdateError.UnknownError;
switch (state)
{
case AssetUpdateState.GetUpdateInfo:
{
var httpAction = ConvertAction<HttpsGetAction>(_currentAction);
error = AssetUpdateError.AssetJsonError;
if (httpAction != null)
{
JsonAssetInfo jsonAssetInfo = HandleHttpGetAction(httpAction);
Debug.Log("更新资源信息: " + jsonAssetInfo);
2024-08-23 15:49:34 +08:00
if (jsonAssetInfo == null)
Debug.LogError("Failed to convert jsonData to JsonAssetInfo");
else
{
assetUri = jsonAssetInfo.assetUri;
2024-08-23 15:49:34 +08:00
assetVersion = jsonAssetInfo.assetVersion;
apkUri = jsonAssetInfo.apkUri;
apkVersion = jsonAssetInfo.apkVersion;
2024-08-23 15:49:34 +08:00
error = apkVersion == Application.version
? AssetUpdateError.Success
: AssetUpdateError.ApkUpdate;
}
}
}
break;
case AssetUpdateState.DownloadAssetList:
{
var assetInfoAction = ConvertAction<AssetVersionAction>(_currentAction);
if (assetInfoAction != null)
{
error = assetInfoAction.error;
if (error == AssetUpdateError.Success)
mainInfo = assetInfoAction.mainInfo;
}
}
break;
case AssetUpdateState.CompareAssetList:
{
var assetCompareAction = ConvertAction<AssetCompareAction>(_currentAction);
if (assetCompareAction != null)
{
downloadList = assetCompareAction.downloadList;
2024-08-23 15:49:34 +08:00
streamingPathInfo = assetCompareAction.streamingPathInfo;
error = AssetUpdateError.Success;
2024-08-23 15:49:34 +08:00
}
}
break;
case AssetUpdateState.DownloadFile:
{
var downloadAction = ConvertAction<ProjectDownloadAction>(_currentAction);
if (downloadAction != null)
error = downloadAction.error;
}
break;
case AssetUpdateState.Complete:
case AssetUpdateState.Error:
break;
default:
{
Debug.LogError(string.Format("Unhandled state {0} in StartCurrentAction", state));
}
break;
}
}
private void HandleStateError()
{
var errorState = state;
state = AssetUpdateState.Error;
Debug.LogError("Error on Step " + errorState);
switch (error)
{
case AssetUpdateError.AssetJsonError:
{
LiteConfirmWin.Open("资源同步错误", "无法获得服务器文件版本号!\n请在网络通畅的情况下再次尝试",
new LiteConfirmButtonData("确定", RestartProcess));
2024-08-23 15:49:34 +08:00
}
break;
case AssetUpdateError.VersionDataError:
{
LiteConfirmWin.Open("资源清单错误", "无法获得正确的服务器文件清单!\n请在网络通畅的情况下再次尝试",
new LiteConfirmButtonData("确定", RestartProcess));
2024-08-23 15:49:34 +08:00
}
break;
case AssetUpdateError.DownloadError:
{
LiteConfirmWin.Open("资源下载错误", "无法下载所需文件!\n请在网络通畅的情况下再次尝试",
new LiteConfirmButtonData("确定", RestartProcess));
2024-08-23 15:49:34 +08:00
}
break;
case AssetUpdateError.FileCreateError:
{
LiteConfirmWin.Open("读写错误", "无法更新资源文件!\n请检查硬盘容量并确保游戏拥有响应读写权限",
new LiteConfirmButtonData("确定", RestartProcess));
2024-08-23 15:49:34 +08:00
}
break;
case AssetUpdateError.ApkError:
case AssetUpdateError.ApkUpdate:
{
OpenApkUri(apkUri);
}
break;
case AssetUpdateError.UserCancel:
{
// 用户自行选择取消更新
RestartProcess();
}
break;
default:
{
Debug.LogError(string.Format("Unhandled error type {0} in HandleStateError", error));
LiteConfirmWin.Open("网络错误", "无法获得服务器列表\n请在网络通畅的情况下再次尝试",
new LiteConfirmButtonData("确定", RestartProcess));
2024-08-23 15:49:34 +08:00
}
break;
}
}
private void OnAllActionComplete()
{
_currentAction = null;
TryToEndProcess();
}
private static void OnApkUpdateConfirm(string uri)
{
Debug.Log(string.Format("Open apk uri at {0}!", uri));
Application.OpenURL(uri);
// 锁死当前界面,防止用户关闭浏览器后,需要重启唤起
OpenApkUri(uri);
}
public static void OpenApkUri(string uri)
{
LiteConfirmWin.Open("安装包更新", "点击确定从商店下载最新版本的游戏安装包!\n" + uri,
new LiteConfirmButtonData("确定", () => OnApkUpdateConfirm(uri)));
2024-08-23 15:49:34 +08:00
}
2024-08-23 15:49:34 +08:00
private void RestartProcess()
{
SceneHub.LoadScene(SceneHub.GetActiveScene().name);
}
private void Update()
{
if (state < AssetUpdateState.Complete && _currentAction != null)
// 完成当前Action
if (_currentAction.UpdateTimeout())
{
// 从当前Action中读取错误码
EndCurrentAction();
if (error == AssetUpdateError.Success)
{
state++;
if (state == AssetUpdateState.Complete)
OnAllActionComplete();
else
StartCurrentAction();
}
else
{
HandleStateError();
}
}
}
private void TryToEndProcess()
{
// if (_complete && _ui.complete) EndProcess();
GameObject.DestroyObject(this);
2024-08-23 15:49:34 +08:00
if (state == AssetUpdateState.Complete)
StartGame();
}
private void StartGame()
{
SaveCurrentVersion();
SceneHub.LoadScene(GlobeVar.sceneLogin);
}
#region
public enum AssetUpdateState
{
GetUpdateInfo,
DownloadAssetList,
CompareAssetList,
DownloadFile,
Complete,
Error
}
public enum AssetUpdateError
{
Success,
FileCreateError,
AssetJsonError,
VersionDataError,
DownloadError,
ApkError,
UserCancel,
ApkUpdate,
UnknownError
}
#endregion
}