更新HybirdCLR Procedure

更新HybirdCLR Procedure
This commit is contained in:
ALEXTANG
2022-10-25 11:06:27 +08:00
parent 3146dfdc73
commit 54ff5fab41
23 changed files with 99 additions and 124 deletions

View File

@@ -0,0 +1,345 @@
using System;
using System.Collections.Generic;
using TEngine.Runtime.HotUpdate;
using UnityEngine;
using UnityEngine.Networking;
namespace TEngine.Runtime
{
/// <summary>
/// 流程加载器 - 检查版本更新
/// </summary>
public class ProcedureCheckVersion:ProcedureBase
{
private bool m_CheckVersionComplete = false;
private bool m_NeedUpdateVersion = false;
private OnlineVersionInfo m_VersionInfo = null;
private UnityWebRequest m_UnityWebRequest;
private UnityWebRequestAsyncOperation m_result;
private int _curTryCount;
private const int MaxTryCount = 3;
private void PreLoadHotUpdate()
{
//热更新阶段文本初始化
LoadText.Instance.InitConfigData(null);
//热更新UI初始化
UILoadMgr.Initialize();
UILoadMgr.Show(UIDefine.UILoadUpdate);
}
protected override void OnEnter(IFsm<IProcedureManager> procedureOwner)
{
base.OnEnter(procedureOwner);
m_CheckVersionComplete = false;
m_NeedUpdateVersion = false;
m_VersionInfo = null;
PreLoadHotUpdate();
RequestVersion();
}
/// <summary>
/// 请求热更数据
/// </summary>
private void RequestVersion()
{
_curTryCount++;
if (_curTryCount > MaxTryCount)
{
LoaderUtilities.ShowMessageBox(LoadText.Instance.Label_Net_Error, MessageShowType.TwoButton,
LoadStyle.StyleEnum.Style_Retry,
() => {
_curTryCount = 0;
RequestVersion();
}, () =>
{
Application.Quit();
});
return;
}
var checkVersionUrl = Utility.Text.Format(HotUpdateMgr.Instance.BuildInfo.CheckVersionUrl,
GetPlatformPath());
UILoadMgr.Show(UIDefine.UILoadUpdate, string.Format(LoadText.Instance.Label_Load_Checking, _curTryCount));
if (string.IsNullOrEmpty(checkVersionUrl))
{
TLogger.LogError("LoadMgr.RequestVersion, remote url is empty or null");
LoaderUtilities.ShowMessageBox(LoadText.Instance.Label_RemoteUrlisNull, MessageShowType.OneButton,
LoadStyle.StyleEnum.Style_QuitApp,
Application.Quit);
return;
}
TLogger.LogInfo("LoadMgr.RequestVersion, proxy:" + checkVersionUrl);
Log.Info($"Check Version Url=>{checkVersionUrl}");
m_UnityWebRequest = UnityWebRequest.Get(checkVersionUrl);
m_result = m_UnityWebRequest.SendWebRequest();
}
private LoadData GenLoadData()
{
var onlineResListUrl = m_VersionInfo.UpdatePrefixUri + "/" + m_VersionInfo.ResourceVersion +"/";
Log.Warning(onlineResListUrl);
string resListStr = string.Empty;
try
{
resListStr = LoaderUtilities.HttpGet(onlineResListUrl + "Md5List.json");
}
catch (Exception e)
{
LoaderUtilities.ShowMessageBox(LoadText.Instance.Label_Net_Error+e.Message, MessageShowType.TwoButton,
LoadStyle.StyleEnum.Style_Retry,
() => {
RequestVersion();
}, () =>
{
Application.Quit();
});
return null;
}
var resDic = (Dictionary<string, object>)MiniJSON.Json.Deserialize(resListStr);
List<object> resList = (List<object>)resDic["_target"];
var data = new LoadData();
data.Type = UpdateType.ResourceUpdate;
data.Style = UpdateStyle.Optional;
data.Notice = UpdateNotice.Notice;
data.Type = m_VersionInfo.UpdateType;
if (GameConfig.Instance.ResId == m_VersionInfo.ResourceVersion.ToString())
{
TLogger.LogInfo("GameConfig.Instance.ResId 匹配,无需更新");
UILoadMgr.Show(UIDefine.UILoadUpdate, "校验资源版中...");
LoaderUtilities.DelayFun((() =>
{
UILoadMgr.Show(UIDefine.UILoadUpdate, "资源版校验完成!!!");
}), new WaitForSeconds(1f));
LoaderUtilities.DelayFun((() =>
{
UILoadMgr.HideAll();
}),new WaitForSeconds(2f));
data.Type = UpdateType.None;
}
if (data.Type != UpdateType.PackageUpdate)
{
data.Style = m_VersionInfo.UpdateStyle;
data.Notice = m_VersionInfo.UpdateNotice;
}
data.List = new List<LoadResource>();
data.All = new List<LoadResource>();
if (resList != null)
{
for (int i = 0; i < resList.Count; i++)
{
var item = (Dictionary<string, object>)resList[i];
string fileName = item["fileName"].ToString();
var itemTemp = new LoadResource
{
RemoteUrl = onlineResListUrl + fileName,
Md5 = item["md5"].ToString(),
Size = (long)item["fileSize"],
Url = fileName,
};
data.List.Add(itemTemp);
data.All.Add(itemTemp);
}
}
return data;
}
protected override void OnUpdate(IFsm<IProcedureManager> procedureOwner, float elapseSeconds, float realElapseSeconds)
{
base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds);
if (m_result == null || !m_result.isDone)
{
return;
}
else
{
CheckWebRequest();
}
if (!m_CheckVersionComplete)
{
return;
}
if (m_NeedUpdateVersion)
{
var data = GenLoadData();
if (data == null)
{
m_UnityWebRequest.Dispose();
m_result = null;
m_UnityWebRequest = null;
return;
}
procedureOwner.SetData<LoadData>("LoadData", data);
procedureOwner.SetData<OnlineVersionInfo>("OnlineVersionInfo", m_VersionInfo);
ChangeState<ProcedureResourcesUpdate>(procedureOwner);
}
else
{
var data = GenLoadData();
if (data == null)
{
m_UnityWebRequest.Dispose();
m_result = null;
m_UnityWebRequest = null;
return;
}
procedureOwner.SetData<LoadData>("LoadData", data);
procedureOwner.SetData<OnlineVersionInfo>("OnlineVersionInfo", m_VersionInfo);
ChangeState<ProcedureCodeInit>(procedureOwner);
}
}
/// <summary>
/// 检测版本检查网络请求
/// </summary>
private void CheckWebRequest()
{
if (m_result == null || !m_result.isDone)
{
return;
}
if (m_UnityWebRequest != null && m_UnityWebRequest.isDone)
{
if (m_UnityWebRequest.error == null)
{
byte[] versionInfoBytes = m_UnityWebRequest.downloadHandler.data;
string versionInfoString = Utility.Converter.GetString(versionInfoBytes);
m_VersionInfo = Utility.Json.ToObject<OnlineVersionInfo>(versionInfoString);
if (m_VersionInfo == null)
{
Log.Fatal("Parse VersionInfo failure.");
return;
}
Log.Info("Latest game version is '{0} ({1})', local game version is '{2} ({3})'.",
m_VersionInfo.GameVersion,
m_VersionInfo.InternalResourceVersion.ToString(),
Version.GameVersion,
Version.InternalGameVersion.ToString());
Log.Warning("GameConfig.Instance.ResId " + GameConfig.Instance.ResId);
Log.Warning("Version.ResourceVersion " + m_VersionInfo.ResourceVersion);
if (string.Equals(GameConfig.Instance.ResId, m_VersionInfo.ResourceVersion.ToString()))
{
m_NeedUpdateVersion = false;
}
else
{
m_NeedUpdateVersion = true;
}
m_CheckVersionComplete = true;
}
else
{
Log.Fatal($"Check version failure :{m_UnityWebRequest.error}");
m_UnityWebRequest.Dispose();
m_result = null;
m_UnityWebRequest = null;
LoaderUtilities.DelayFun(RequestVersion, new WaitForSeconds(1f));
}
}
}
/// <summary>
/// 跳转到APP下载路径
/// </summary>
/// <param name="userData"></param>
private void GotoUpdateApp(object userData)
{
string url = null;
#if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN
url = HotUpdateMgr.Instance.BuildInfo.WindowsAppUrl;
#elif UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX
url = HotUpdateMgr.Instance.BuildInfo.MacOSAppUrl;
#elif UNITY_IOS
url = HotUpdateMgr.Instance.BuildInfo.IOSAppUrl;
#elif UNITY_ANDROID
url = HotUpdateMgr.Instance.BuildInfo.AndroidAppUrl;
#endif
if (!string.IsNullOrEmpty(url))
{
Application.OpenURL(url);
}
}
/// <summary>
/// 获取不同平台的资源检测路径
/// </summary>
/// <returns></returns>
private string GetPlatformPath()
{
#if UNITY_EDITOR
#if UNITY_STANDALONE_WIN
return "Windows";
#elif UNITY_EDITOR_OSX
return "IOS";
#elif UNITY_IOS
return "IOS";
#elif UNITY_ANDROID
return "Android";
#else
return "Unknow"
#endif
#else
// 这里和 PlatformUtility.GetPlatformPath() 对应。由 Unity.RuntimePlatform 得到 平台标识符
switch (Application.platform)
{
case RuntimePlatform.WindowsEditor:
case RuntimePlatform.WindowsPlayer:
return "Windows";
case RuntimePlatform.OSXEditor:
case RuntimePlatform.OSXPlayer:
return "MacOS";
case RuntimePlatform.IPhonePlayer:
return "IOS";
case RuntimePlatform.Android:
return "Android";
case RuntimePlatform.WSAPlayerX64:
case RuntimePlatform.WSAPlayerX86:
case RuntimePlatform.WSAPlayerARM:
return "WSA";
case RuntimePlatform.WebGLPlayer:
return "WebGL";
case RuntimePlatform.LinuxEditor:
case RuntimePlatform.LinuxPlayer:
return "Linux";
default:
Log.Fatal(Application.platform.ToString());
throw new System.NotSupportedException(Utility.Text.Format("Platform '{0}' is not supported.", Application.platform));
}
#endif
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b4174e49b2cd17241878ed96673b9785
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,115 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using HybridCLR;
using UnityEngine;
namespace TEngine.Runtime
{
/// <summary>
/// 流程加载器 - 代码初始化
/// </summary>
public class ProcedureCodeInit : ProcedureBase
{
public static List<string> AOTMetaAssemblyNames { get; } = new List<string>()
{
"mscorlib.dll",
"System.dll",
"System.Core.dll",
};
/// <summary>
/// 为aot assembly加载原始metadata 这个代码放aot或者热更新都行。
/// 一旦加载后如果AOT泛型函数对应native实现不存在则自动替换为解释模式执行
/// </summary>
private static void LoadMetadataForAOTAssemblies()
{
// 可以加载任意aot assembly的对应的dll。但要求dll必须与unity build过程中生成的裁剪后的dll一致而不能直接使用原始dll。
// 我们在BuildProcessors里添加了处理代码这些裁剪后的dll在打包时自动被复制到 {项目目录}/HybridCLRData/AssembliesPostIl2CppStrip/{Target} 目录。
// 注意补充元数据是给AOT dll补充元数据而不是给热更新dll补充元数据。
// 热更新dll不缺元数据不需要补充如果调用LoadMetadataForAOTAssembly会返回错误
foreach (var aotDllName in AOTMetaAssemblyNames)
{
byte[] dllBytes = TResources.Load<TextAsset>(aotDllName).bytes;
if (dllBytes == null)
{
Log.Fatal($"{aotDllName} is null");
continue;
}
// 加载assembly对应的dll会自动为它hook。一旦aot泛型函数的native函数不存在用解释器版本代码
LoadImageErrorCode err = RuntimeApi.LoadMetadataForAOTAssembly(dllBytes);
Log.Info($"LoadMetadataForAOTAssembly:{aotDllName}. ret:{err}");
}
}
/// <summary>
/// 是否需要加载热更新DLL
/// </summary>
public bool NeedLoadDll => ResourceComponent.Instance.ResourceMode == ResourceMode.Updatable || ResourceComponent.Instance.ResourceMode == ResourceMode.UpdatableWhilePlaying;
private IFsm<IProcedureManager> m_procedureOwner;
protected override void OnEnter(IFsm<IProcedureManager> procedureOwner)
{
base.OnEnter(procedureOwner);
m_procedureOwner = procedureOwner;
if (!NeedLoadDll)
{
ChangeState<ProcedureStartGame>(procedureOwner);
return;
}
LoadMetadataForAOTAssemblies();
#if UNITY_EDITOR
Assembly hotfixAssembly = System.AppDomain.CurrentDomain.GetAssemblies().First(assembly => assembly.GetName().Name == "Assembly-CSharp");
StartHotfix(hotfixAssembly);
#else
TResources.LoadAsync<TextAsset>("Dll/HotFix.dll.bytes", (data =>
{
if (data == null)
{
OnLoadAssetFail();
return;
}
var obj = data as TextAsset;
if (obj == null)
{
OnLoadAssetFail();
return;
}
else
{
OnLoadAssetSuccess(obj);
}
}));
#endif
}
private void OnLoadAssetSuccess(TextAsset asset)
{
TextAsset dll = (TextAsset)asset;
Assembly hotfixAssembly = System.Reflection.Assembly.Load(dll.bytes);
Log.Info("Load hotfix dll OK.");
StartHotfix(hotfixAssembly);
}
private void OnLoadAssetFail()
{
Log.Error("Load hotfix dll failed. ");
}
private void StartHotfix(Assembly hotfixAssembly)
{
var hotfixEntry = hotfixAssembly.GetType("HotFix.GameHotfixEntry");
var start = hotfixEntry.GetMethod("Start");
start?.Invoke(null, null);
ChangeState<ProcedureStartGame>(m_procedureOwner);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 727c047191bf562408cd171d83ba3d61
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,15 @@
namespace TEngine.Runtime
{
/// <summary>
/// 流程加载器 - 开始起点
/// </summary>
public class ProcedureLaunch : ProcedureBase
{
protected override void OnUpdate(IFsm<IProcedureManager> procedureOwner, float elapseSeconds, float realElapseSeconds)
{
base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds);
ChangeState<ProcedureSplash>(procedureOwner);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 31acbba6c65c0314985944275895f1c0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,47 @@
using UnityEngine;
namespace TEngine.Runtime
{
/// <summary>
/// 流程加载器 - 资源初始化
/// </summary>
public class ProcedureResourcesInit : ProcedureBase
{
private bool m_initResourceComplete = false;
protected override void OnEnter(IFsm<IProcedureManager> procedureOwner)
{
base.OnEnter(procedureOwner);
GameEventMgr.Instance.AddEventListener("OnInitResourceComplete", OnInitResourceComplete);
m_initResourceComplete = false;
LoaderUtilities.DelayFun((() =>
{
GameEventMgr.Instance.Send("OnInitResourceComplete");
}),new WaitForSeconds(1f));
}
protected override void OnUpdate(IFsm<IProcedureManager> procedureOwner, float elapseSeconds, float realElapseSeconds)
{
base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds);
if (m_initResourceComplete)
{
ChangeState<ProcedureCodeInit>(procedureOwner);
}
}
protected override void OnLeave(IFsm<IProcedureManager> procedureOwner, bool isShutdown)
{
base.OnLeave(procedureOwner, isShutdown);
GameEventMgr.Instance.RemoveEventListener("OnInitResourceComplete", OnInitResourceComplete);
}
private void OnInitResourceComplete()
{
m_initResourceComplete = true;
Log.Info("OnInitResourceComplete 初始化资源完成");
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 22e55cee812c74f4d9e831d604e3fa33
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,199 @@
using System;
using TEngine.Runtime.HotUpdate;
using UnityEngine;
namespace TEngine.Runtime
{
/// <summary>
/// 流程加载器 - 资源下载/资源热更新/资源校验
/// </summary>
internal class ProcedureResourcesUpdate : ProcedureBase
{
private LoadData _currentData;
private OnlineVersionInfo _onlineVersionInfo;
private IFsm<IProcedureManager> _procedureOwner;
private bool _dllLoad = false;
protected override void OnEnter(IFsm<IProcedureManager> procedureOwner)
{
base.OnEnter(procedureOwner);
GameEventMgr.Instance.AddEventListener<bool>("DownLoadResult.AllDownLoaded",AllDownLoaded);
_procedureOwner = procedureOwner;
_currentData = procedureOwner.GetData<LoadData>("LoadData");
_onlineVersionInfo = procedureOwner.GetData<OnlineVersionInfo>("OnlineVersionInfo");
_currentData.List = LoadMgr.Instance.CheckLocalExitResource(_currentData.List);
if (_currentData.List.Count <= 0)
{
LoadMgr.Instance.DownLoadCallBack((int)DownLoadResult.AllDownLoaded, GameStatus.AssetLoad, _currentData.All);
}
else
{
ShowUpdateType(_currentData);
}
}
/// <summary>
/// 显示更新方式
/// </summary>
/// <returns></returns>
private bool ShowUpdateType(LoadData data)
{
UILoadMgr.Show(UIDefine.UILoadUpdate, LoadText.Instance.Label_Load_Checked);
//底包更新
if (data.Type == UpdateType.PackageUpdate)
{
LoaderUtilities.ShowMessageBox(LoadText.Instance.Label_Load_Package, MessageShowType.OneButton,
LoadStyle.StyleEnum.Style_DownLoadApk,
() =>
{
LoadMgr.Instance.StartUpdate(data.List);
});
return true;
}
//资源更新
else if (data.Type == UpdateType.ResourceUpdate)
{
//强制
if (data.Style == UpdateStyle.Froce)
{
//提示
if (data.Notice == UpdateNotice.Notice)
{
NetworkReachability n = Application.internetReachability;
string desc = LoadText.Instance.Label_Load_Force_WIFI;
if (n == NetworkReachability.ReachableViaCarrierDataNetwork)
{
desc = LoadText.Instance.Label_Load_Force_NO_WIFI;
}
long totalSize = 0;
foreach (var item in data.List)
{
totalSize += item.Size;
}
desc = string.Format(desc, LoaderUtilities.FormatData(totalSize));
LoaderUtilities.ShowMessageBox(desc, MessageShowType.TwoButton,
LoadStyle.StyleEnum.Style_StartUpdate_Notice,
() =>
{
LoadMgr.Instance.StartUpdate(data.List);
}, () =>
{
StartGame();
});
}
//不提示
else if (data.Notice == UpdateNotice.NoNotice)
{
LoadMgr.Instance.StartUpdate(data.List);
}
}
//非强制
else if (data.Style == UpdateStyle.Optional)
{
//提示
if (data.Notice == UpdateNotice.Notice)
{
LoaderUtilities.ShowMessageBox(LoadText.Instance.Label_Load_Notice, MessageShowType.TwoButton,
LoadStyle.StyleEnum.Style_StartUpdate_Notice,
() =>
{
LoadMgr.Instance.StartUpdate(data.List);
}, () =>
{
StartGame();
});
}
//不提示
else if (data.Notice == UpdateNotice.NoNotice)
{
LoadMgr.Instance.StartUpdate(data.List);
}
}
else
TLogger.LogError("LoadMgr._CheckUpdate, style is error,code:" + data.Style);
return true;
}
//没有更新
return false;
}
private void StartGame()
{
ChangeState<ProcedureStartGame>(_procedureOwner);
}
/// <summary>
/// 全部下载完成回调
/// </summary>
/// <param name="result"></param>
private void AllDownLoaded(bool result)
{
if (result)
{
try
{
if (string.IsNullOrEmpty(_onlineVersionInfo.ResourceVersion.ToString()))
{
_onlineVersionInfo.ResourceVersion = int.Parse(GameConfig.Instance.ResId);
}
GameConfig.Instance.WriteResVersion(_onlineVersionInfo.ResourceVersion.ToString());
UILoadMgr.Show(UIDefine.UILoadUpdate, "所有资源下载完成,稍后进入游戏!");
LoaderUtilities.DelayFun((() =>
{
UILoadMgr.HideAll();
}), new WaitForSeconds(2));
}
catch (Exception e)
{
TLogger.LogError(e.StackTrace);
LoaderUtilities.ShowMessageBox(LoadText.Instance.Label_Load_UnPackError, MessageShowType.OneButton,
LoadStyle.StyleEnum.Style_RestartApp,
() =>
{
Application.Quit();
});
return;
}
if (_dllLoad == false)
{
StartGame();
}
else
{
LoaderUtilities.ShowMessageBox(LoadText.Instance.Label_RestartApp, MessageShowType.OneButton,
LoadStyle.StyleEnum.Style_RestartApp,
() =>
{
Application.Quit();
});
}
}
else
{
foreach (var item in _currentData.List)
{
if (item.Url == null)
{
continue;
}
LoaderUtilities.DeleteFile(FileSystem.ResourceRoot + "/" + item.Url);
}
LoaderUtilities.ShowMessageBox(LoadText.Instance.Label_Load_UnPackError, MessageShowType.OneButton,
LoadStyle.StyleEnum.Style_QuitApp,
() => {
Application.Quit();
});
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2b4949e6ae6db604e8e24cd52f27889f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,29 @@

namespace TEngine.Runtime
{
/// <summary>
/// 流程加载器 - 资源校验(暂无)
/// </summary>
internal class ProcedureResourcesVerify:ProcedureBase
{
private bool m_VerifyResourcesComplete = false;
protected override void OnUpdate(IFsm<IProcedureManager> procedureOwner, float elapseSeconds, float realElapseSeconds)
{
base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds);
if (!m_VerifyResourcesComplete)
{
return;
}
ChangeState<ProcedureCodeInit>(procedureOwner);
}
private void OnVerifyResourcesComplete(bool result)
{
m_VerifyResourcesComplete = true;
Log.Info("Verify resources complete, result is '{0}'.", result);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7e515393a43f24f459c7d87a50d78084
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TEngine.Runtime
{
/// <summary>
/// 流程加载器 - 闪屏
/// </summary>
public class ProcedureSplash : ProcedureBase
{
protected override void OnInit(IFsm<IProcedureManager> procedureOwner)
{
base.OnInit(procedureOwner);
}
protected override void OnEnter(IFsm<IProcedureManager> procedureOwner)
{
base.OnEnter(procedureOwner);
}
protected override void OnUpdate(IFsm<IProcedureManager> procedureOwner, float elapseSeconds,
float realElapseSeconds)
{
base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds);
// TODO: 这里可以播放一个 Splash 动画
// ...
if (ResourceComponent.Instance.ResourceMode == ResourceMode.Package)
{
Log.Info("单机模式 ChangeState<ProcedureInitResources>");
ChangeState<ProcedureResourcesInit>(procedureOwner);
}
else
{
Log.Info("可更新模式 ChangeState<ProcedureCheckVersion>");
ChangeState<ProcedureCheckVersion>(procedureOwner);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cea4ebefaac8fbd468eb0b3591277ec6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,19 @@
namespace TEngine.Runtime
{
public static partial class TEngineEvent
{
public static readonly int OnStartGame = StringId.StringToHash("TEngineEvent.OnStartGame");
}
/// <summary>
/// 流程加载器 - 终点StartGame
/// </summary>
public class ProcedureStartGame : ProcedureBase
{
protected override void OnEnter(IFsm<IProcedureManager> procedureOwner)
{
base.OnEnter(procedureOwner);
GameEventMgr.Instance.Send(TEngineEvent.OnStartGame);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e7fd9e9398439a34197e5e3c73094987
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: