2024-08-23 15:49:34 +08:00
|
|
|
|
// 在AssetBundleManager等资源管理器生成前,预先处理资源问题的管理器
|
|
|
|
|
// 提前处理资源更新,服务器列表下载等一系列情况
|
|
|
|
|
// 注:这个东西运作的时候,没有AssetBundle,没有Lua,不要试图做任何相关操作。
|
2024-09-23 22:56:51 +08:00
|
|
|
|
|
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; }
|
2024-09-23 22:56:51 +08:00
|
|
|
|
|
|
|
|
|
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-09-23 22:56:51 +08:00
|
|
|
|
|
2024-08-23 15:49:34 +08:00
|
|
|
|
private static bool _useResources = true;
|
|
|
|
|
|
2024-09-23 22:56:51 +08:00
|
|
|
|
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
|
|
|
|
|
2024-09-23 22:56:51 +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-09-23 22:56:51 +08:00
|
|
|
|
|
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-09-23 22:56:51 +08:00
|
|
|
|
|
2024-08-23 15:49:34 +08:00
|
|
|
|
return currentVersion;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void SaveCurrentVersion()
|
|
|
|
|
{
|
|
|
|
|
PlayerPrefs.SetInt(currentVersionPref, assetVersion);
|
|
|
|
|
}
|
2024-09-23 22:56:51 +08:00
|
|
|
|
|
2024-08-23 15:49:34 +08:00
|
|
|
|
private void Awake()
|
|
|
|
|
{
|
2024-09-23 22:56:51 +08:00
|
|
|
|
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)
|
|
|
|
|
{
|
2024-09-23 22:56:51 +08:00
|
|
|
|
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
|
|
|
|
|
{
|
2024-09-23 22:56:51 +08:00
|
|
|
|
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-09-23 22:56:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
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;
|
2024-09-23 22:56:51 +08:00
|
|
|
|
state = AssetUpdateState.GetUpdateInfo;
|
2024-08-23 15:49:34 +08:00
|
|
|
|
StartCurrentAction();
|
|
|
|
|
}
|
2024-09-23 22:56:51 +08:00
|
|
|
|
|
2024-08-23 15:49:34 +08:00
|
|
|
|
FirstSceneBg.instance.ShowGameVersion();
|
|
|
|
|
// 清理上次执行残留的rawJsonText
|
|
|
|
|
// 当前项目没有类似数据缓存库一样的类,暂时直接用静态传递
|
|
|
|
|
assetUri = string.Empty;
|
2024-09-23 22:56:51 +08:00
|
|
|
|
state = AssetUpdateState.GetUpdateInfo;
|
2024-08-23 15:49:34 +08:00
|
|
|
|
StartCurrentAction();
|
|
|
|
|
}
|
2024-09-23 22:56:51 +08:00
|
|
|
|
|
2024-08-23 15:49:34 +08:00
|
|
|
|
private void Start()
|
|
|
|
|
{
|
|
|
|
|
// 特别处理Android Resume时期的诡异情况,该状况下,AssetBundle未被清空,但实际Bundle管理器已被析构
|
|
|
|
|
AssetBundle.UnloadAllAssetBundles(true);
|
2024-09-23 22:56:51 +08:00
|
|
|
|
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-09-23 22:56:51 +08:00
|
|
|
|
|
2024-08-23 15:49:34 +08:00
|
|
|
|
return jsonAssetInfo;
|
|
|
|
|
}
|
2024-09-23 22:56:51 +08:00
|
|
|
|
|
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)
|
|
|
|
|
{
|
2024-09-24 03:15:21 +08:00
|
|
|
|
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
|
|
|
|
|
{
|
2024-09-23 22:56:51 +08:00
|
|
|
|
assetUri = jsonAssetInfo.assetUri;
|
2024-08-23 15:49:34 +08:00
|
|
|
|
assetVersion = jsonAssetInfo.assetVersion;
|
2024-09-23 22:56:51 +08:00
|
|
|
|
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)
|
|
|
|
|
{
|
2024-09-23 22:56:51 +08:00
|
|
|
|
downloadList = assetCompareAction.downloadList;
|
2024-08-23 15:49:34 +08:00
|
|
|
|
streamingPathInfo = assetCompareAction.streamingPathInfo;
|
2024-09-23 22:56:51 +08:00
|
|
|
|
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请在网络通畅的情况下再次尝试!",
|
2024-09-23 22:56:51 +08:00
|
|
|
|
new LiteConfirmButtonData("确定", RestartProcess));
|
2024-08-23 15:49:34 +08:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case AssetUpdateError.VersionDataError:
|
|
|
|
|
{
|
|
|
|
|
LiteConfirmWin.Open("资源清单错误", "无法获得正确的服务器文件清单!\n请在网络通畅的情况下再次尝试!",
|
2024-09-23 22:56:51 +08:00
|
|
|
|
new LiteConfirmButtonData("确定", RestartProcess));
|
2024-08-23 15:49:34 +08:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case AssetUpdateError.DownloadError:
|
|
|
|
|
{
|
|
|
|
|
LiteConfirmWin.Open("资源下载错误", "无法下载所需文件!\n请在网络通畅的情况下再次尝试!",
|
2024-09-23 22:56:51 +08:00
|
|
|
|
new LiteConfirmButtonData("确定", RestartProcess));
|
2024-08-23 15:49:34 +08:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case AssetUpdateError.FileCreateError:
|
|
|
|
|
{
|
|
|
|
|
LiteConfirmWin.Open("读写错误", "无法更新资源文件!\n请检查硬盘容量,并确保游戏拥有响应读写权限!",
|
2024-09-23 22:56:51 +08:00
|
|
|
|
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请在网络通畅的情况下再次尝试!",
|
2024-09-23 22:56:51 +08:00
|
|
|
|
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,
|
2024-09-23 22:56:51 +08:00
|
|
|
|
new LiteConfirmButtonData("确定", () => OnApkUpdateConfirm(uri)));
|
2024-08-23 15:49:34 +08:00
|
|
|
|
}
|
2024-09-23 22:56:51 +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();
|
2024-09-23 22:56:51 +08:00
|
|
|
|
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
|
|
|
|
|
}
|