mirror of
https://gitee.com/jisol/jisol-game/
synced 2025-09-27 02:36:14 +00:00
提交热更新
This commit is contained in:
@@ -1,13 +1,11 @@
|
||||
using System.IO;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using Plugins.SHFrame.SHGame.YooAsset;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using HotMain.SHGame.YooAsset;
|
||||
using HotMain.SHGame.YooAsset.StreamingAssetsHelper;
|
||||
using SHFrame;
|
||||
using SHFrame.FSM;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using YooAsset;
|
||||
|
||||
namespace Plugins.SHFrame.SHGame.Procedure
|
||||
namespace HotMain.SHGame.Procedure
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化资源包
|
||||
@@ -15,7 +13,7 @@ namespace Plugins.SHFrame.SHGame.Procedure
|
||||
public class ProcedureInitializePackage : ProcedureBase
|
||||
{
|
||||
|
||||
public static EPlayMode PlayMode = EPlayMode.OfflinePlayMode;
|
||||
public static EPlayMode PlayMode = EPlayMode.HostPlayMode;
|
||||
public static string RawFilePackageName = "RawFilePackage";
|
||||
public static string DefaultPackageName = "DefaultPackage";
|
||||
|
||||
@@ -23,6 +21,7 @@ namespace Plugins.SHFrame.SHGame.Procedure
|
||||
//热更新的dll名称
|
||||
public static readonly string[] HotDllName =
|
||||
{
|
||||
"HotSamples.dll"
|
||||
};
|
||||
|
||||
public static readonly string[] AotMetaAssemblyFiles =
|
||||
@@ -85,13 +84,14 @@ namespace Plugins.SHFrame.SHGame.Procedure
|
||||
initOperation = package.InitializeAsync(initParametersOfflinePlayMode);
|
||||
break;
|
||||
case EPlayMode.HostPlayMode:
|
||||
// //联机运行模式
|
||||
// var initParametersHostPlayMode = new HostPlayModeParameters
|
||||
// {
|
||||
// BuildinQueryServices = new GameQueryServices(),
|
||||
// RemoteServices = new RemoteServices(GetHostServerURL(packageName), GetHostServerURL(packageName))
|
||||
// };
|
||||
// initOperation = package.InitializeAsync(initParametersHostPlayMode);
|
||||
//联机运行模式
|
||||
// 注意:GameQueryServices.cs 太空战机的脚本类,详细见StreamingAssetsHelper.cs
|
||||
string HostServer = $"http://ngame.jisol.cn/JNGame2/{packageName}";
|
||||
var createParameters = new HostPlayModeParameters();
|
||||
createParameters.DecryptionServices = new FileStreamDecryption();
|
||||
createParameters.BuildinQueryServices = new GameQueryServices();
|
||||
createParameters.RemoteServices = new RemoteServices(HostServer, HostServer);
|
||||
initOperation = package.InitializeAsync(createParameters);
|
||||
break;
|
||||
}
|
||||
|
||||
|
59
JNFrame2/Assets/HotMain/SHGame/Procedure/ProcedureLoadHot.cs
Normal file
59
JNFrame2/Assets/HotMain/SHGame/Procedure/ProcedureLoadHot.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
using System.Reflection;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using SHFrame;
|
||||
using UnityEngine;
|
||||
using YooAsset;
|
||||
|
||||
namespace HotMain.SHGame.Procedure
|
||||
{
|
||||
public class ProcedureLoadHot : ProcedureBase
|
||||
{
|
||||
|
||||
protected override void OnEnter(SHFrame.FSM.IFsm<IProcedureManager> procedureOwner)
|
||||
{
|
||||
base.OnEnter(procedureOwner);
|
||||
MainLoad(procedureOwner).Forget();
|
||||
}
|
||||
|
||||
private async UniTask MainLoad(SHFrame.FSM.IFsm<IProcedureManager> procedureOwner)
|
||||
{
|
||||
// 加载热更dll
|
||||
foreach (var name in ProcedureInitializePackage.HotDllName)
|
||||
{
|
||||
await LoadHotfixDll(ProcedureInitializePackage.RawFilePackageName, name);
|
||||
}
|
||||
|
||||
// 实例化热更新入口 执行游戏初始化(配置表初始化、UI模块初始化、获取玩家数据之类的操作)
|
||||
ResourcePackage package = YooAssets.GetPackage(ProcedureInitializePackage.DefaultPackageName);
|
||||
var go = await LoadGameObject(package, "HotPrefab");
|
||||
go.name = $"Resource_{package.GetPackageVersion()}_{YooAssets.GetPackage(ProcedureInitializePackage.RawFilePackageName).GetPackageVersion()}";
|
||||
Log.Warning($"Prefab name is {go.name}");
|
||||
}
|
||||
|
||||
public static async UniTask<Assembly> LoadHotfixDll(string packageName, string name)
|
||||
{
|
||||
Log.Warning($"加载热更dll:{name}");
|
||||
var package = YooAssets.GetPackage(packageName);
|
||||
var handle = package.LoadRawFileAsync(name);
|
||||
await handle.ToUniTask();
|
||||
var dllBytes = handle.GetRawFileData();
|
||||
var assembly = Assembly.Load(dllBytes);
|
||||
Log.Warning($"加载热更dll完成:{name}");
|
||||
return assembly;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步加载GameObject
|
||||
/// </summary>
|
||||
/// <param name="package"></param>
|
||||
/// <param name="assetNames">YooAsset中打包的资源名称</param>
|
||||
/// <returns>返回GameObject</returns>
|
||||
public static async UniTask<GameObject> LoadGameObject(ResourcePackage package, string assetNames)
|
||||
{
|
||||
var handle = package.LoadAssetAsync<GameObject>(assetNames);
|
||||
await handle.ToUniTask();
|
||||
return handle.InstantiateSync();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4dc4cea51e784614969d04772ebdfc68
|
||||
timeCreated: 1728975475
|
@@ -3,7 +3,6 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using HybridCLR;
|
||||
using Plugins.SHFrame.SHGame.Procedure;
|
||||
using SHFrame;
|
||||
using SHFrame.FSM;
|
||||
using YooAsset;
|
||||
@@ -25,6 +24,8 @@ namespace HotMain.SHGame.Procedure
|
||||
// 打包时内置在包体内的资源 直接先使用包体资源,实例化 登录加载界面后,再去检查是否需要下载更新
|
||||
//加载AOT
|
||||
await LoadMetadataForAOTAssemblies();
|
||||
//切换到更新资源版本
|
||||
ChangeState<ProcedurePackageDownloader>(procedureOwner);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -0,0 +1,194 @@
|
||||
using Cysharp.Threading.Tasks;
|
||||
using SHFrame;
|
||||
using SHFrame.FSM;
|
||||
using YooAsset;
|
||||
|
||||
namespace HotMain.SHGame.Procedure
|
||||
{
|
||||
public class ProcedurePackageDownloader : ProcedureBase
|
||||
{
|
||||
|
||||
private int launcherPatchCount = 0;
|
||||
|
||||
private int totalDownloadCount = 0;
|
||||
private long totalDownloadBytes = 0;
|
||||
|
||||
protected override void OnEnter(IFsm<IProcedureManager> procedureOwner)
|
||||
{
|
||||
base.OnEnter(procedureOwner);
|
||||
launcherPatchCount = 0;
|
||||
totalDownloadCount = 0;
|
||||
totalDownloadBytes = 0;
|
||||
Download(procedureOwner);
|
||||
}
|
||||
|
||||
private async void Download(IFsm<IProcedureManager> procedureOwner)
|
||||
{
|
||||
// //检查launcher标签的资源
|
||||
// launcherPatchCount += TryGetTagPatchCount(ProcedureInitializePackage.RawFilePackageName, YooTag.LAUNCHER);
|
||||
// launcherPatchCount += TryGetTagPatchCount(ProcedureInitializePackage.DefaultPackageName, YooTag.LAUNCHER);
|
||||
//
|
||||
// if (launcherPatchCount > 0)
|
||||
// {
|
||||
// Log.Warning("launcher资源需要更新,下载完成后需要重启游戏");
|
||||
// totalDownloadCount += launcherPatchCount;
|
||||
// }
|
||||
|
||||
// 完全通过远端获取的资源,每次启动游戏都检查是否需要更新
|
||||
//TODO 把这个玩意拆分成 1、获取下载文件大小,2、提示总的下载大小,提示确认,3、开始下载
|
||||
ResourcePackage rawFilePackage = YooAssets.GetPackage(ProcedureInitializePackage.RawFilePackageName);
|
||||
totalDownloadBytes += TryDownloadPatch(rawFilePackage);
|
||||
ResourcePackage defaultPackage = YooAssets.GetPackage(ProcedureInitializePackage.DefaultPackageName);
|
||||
totalDownloadBytes += TryDownloadPatch(defaultPackage);
|
||||
|
||||
if (totalDownloadCount > 0 || totalDownloadBytes > 0)
|
||||
{
|
||||
|
||||
Log.Warning("开始下载资源");
|
||||
|
||||
//进行下载
|
||||
var result = await GetDownload(rawFilePackage);
|
||||
if (!result) return;
|
||||
|
||||
//进行下载
|
||||
result = await GetDownload(defaultPackage);
|
||||
if (!result) return;
|
||||
|
||||
//判断launcher资源是否有更新,有就弹窗重启游戏
|
||||
if (launcherPatchCount > 0)
|
||||
{
|
||||
Log.Warning("launcher资源有更新,需要重启游戏");
|
||||
return;
|
||||
}
|
||||
|
||||
// 资源下载完毕
|
||||
Log.Warning("资源下载完毕");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Warning("没有资源需要更新");
|
||||
|
||||
}
|
||||
|
||||
//切换到加载热更包入口
|
||||
ChangeState<ProcedureLoadHot>(procedureOwner);
|
||||
}
|
||||
|
||||
private int TryGetTagPatchCount(string packageName, string tag)
|
||||
{
|
||||
ResourcePackage package = YooAssets.GetPackage(packageName);
|
||||
//4.下载补丁包信息,反馈到弹窗
|
||||
var downloader = package.CreateResourceDownloader(tag, 10, 3, 60);
|
||||
//没有需要下载的资源
|
||||
if (downloader.TotalDownloadCount == 0)
|
||||
{
|
||||
Log.Warning($"{package.PackageName} tag {tag} 没有资源更新");
|
||||
return 0;
|
||||
}
|
||||
|
||||
//需要下载的文件总数和总大小
|
||||
Log.Warning($"{package.PackageName} tag {tag} 文件总数:{downloader.TotalDownloadCount}:::总大小:{downloader.TotalDownloadBytes}");
|
||||
return totalDownloadCount;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="package"></param>
|
||||
private long TryDownloadPatch(ResourcePackage package)
|
||||
{
|
||||
//4.下载补丁包信息,反馈到弹窗
|
||||
var downloader = package.CreateResourceDownloader(10, 3, 60);
|
||||
//没有需要下载的资源
|
||||
if (downloader.TotalDownloadCount == 0)
|
||||
{
|
||||
Log.Warning($"{package.PackageName} all 没有资源更新");
|
||||
return 0;
|
||||
}
|
||||
|
||||
totalDownloadCount++;
|
||||
//需要下载的文件总数和总大小
|
||||
Log.Warning($"{package.PackageName} 文件总数:{downloader.TotalDownloadCount}:::总大小:{downloader.TotalDownloadBytes}");
|
||||
return downloader.TotalDownloadBytes;
|
||||
}
|
||||
|
||||
private async UniTask<bool> GetDownload(ResourcePackage package)
|
||||
{
|
||||
var downloader = package.CreateResourceDownloader(10, 3, 60);
|
||||
|
||||
//注册回调方法
|
||||
downloader.OnDownloadErrorCallback = OnDownloadErrorFunction;
|
||||
downloader.OnDownloadProgressCallback = OnDownloadProgressUpdateFunction;
|
||||
downloader.OnDownloadOverCallback = OnDownloadOverFunction;
|
||||
downloader.OnStartDownloadFileCallback = OnStartDownloadFileFunction;
|
||||
|
||||
//开启下载
|
||||
downloader.BeginDownload();
|
||||
await downloader.ToUniTask();
|
||||
//检测下载结果
|
||||
if (downloader.Status == EOperationStatus.Succeed)
|
||||
{
|
||||
Log.Debug("更新完成!");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//下载失败
|
||||
Log.Error("更新失败!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#region yooasset下载回调函数
|
||||
|
||||
/// <summary>
|
||||
/// 下载数据大小
|
||||
/// </summary>
|
||||
/// <param name="fileName"></param>
|
||||
/// <param name="sizeBytes"></param>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
private void OnStartDownloadFileFunction(string fileName, long sizeBytes)
|
||||
{
|
||||
Log.Debug($"开始下载:文件名:{fileName}, 文件大小:{sizeBytes}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载完成与否
|
||||
/// </summary>
|
||||
/// <param name="isSucceed"></param>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
private void OnDownloadOverFunction(bool isSucceed)
|
||||
{
|
||||
Log.Debug("下载" + (isSucceed ? "成功" : "失败"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新中
|
||||
/// </summary>
|
||||
/// <param name="totalCount"></param>
|
||||
/// <param name="currentCount"></param>
|
||||
/// <param name="totalBytes"></param>
|
||||
/// <param name="currentBytes"></param>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
private void OnDownloadProgressUpdateFunction(int totalCount, int currentCount, long totalBytes, long currentBytes)
|
||||
{
|
||||
Log.Debug($"文件总数:{totalCount}, 已下载文件数:{currentCount}, 下载总大小:{totalBytes}, 已下载大小:{currentBytes}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载出错
|
||||
/// </summary>
|
||||
/// <param name="fileName"></param>
|
||||
/// <param name="error"></param>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
private void OnDownloadErrorFunction(string fileName, string error)
|
||||
{
|
||||
Log.Error($"下载出错:文件名:{fileName}, 错误信息:{error}");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 883e7ebff2f7432f94ecd48ae94a925a
|
||||
timeCreated: 1728963960
|
@@ -3,7 +3,7 @@ using SHFrame;
|
||||
using SHFrame.FSM;
|
||||
using YooAsset;
|
||||
|
||||
namespace Plugins.SHFrame.SHGame.Procedure
|
||||
namespace HotMain.SHGame.Procedure
|
||||
{
|
||||
/// <summary>
|
||||
/// 更新资源清单
|
||||
|
@@ -1,10 +1,9 @@
|
||||
using Cysharp.Threading.Tasks;
|
||||
using HotMain.SHGame.Procedure;
|
||||
using SHFrame;
|
||||
using SHFrame.FSM;
|
||||
using YooAsset;
|
||||
|
||||
namespace Plugins.SHFrame.SHGame.Procedure
|
||||
namespace HotMain.SHGame.Procedure
|
||||
{
|
||||
/// <summary>
|
||||
/// 更新资源版本号
|
||||
|
Reference in New Issue
Block a user