第一句子网 - 唯美句子、句子迷、好句子大全
第一句子网 > 【Unity】 HTFramework框架(十七)Hotfix热更新模块

【Unity】 HTFramework框架(十七)Hotfix热更新模块

时间:2024-04-20 05:51:57

相关推荐

【Unity】 HTFramework框架(十七)Hotfix热更新模块

更新日期:3月11日。

Github源码:[点我获取源码]

Gitee源码:[点我获取源码]

索引

Hotfix热更新模块简介使用Hotfix热更新创建Hotfix环境创建Hotfix流程设置资源加载模式运行Hotfix代码访问外界代码外界代码访问Hotfix代码热修复外界方法运行时检视面板

Hotfix热更新模块简介

以C#反射实现的轻量级热更新框架,开发非常方便,新项目只需要拉取框架源码后,一键即可创建热更新环境,之后便可以用C#正常开发,目前已支持热更新库与外界无障碍交互(无需实时反射),且可以动态修复外界任何方法(以热更新库中方法替换外界方法)

注意:目前不支持IOS平台以及其他不支持JIT的平台,若要全平台支持可以使用可选模块ILHotfix。

使用Hotfix热更新

创建Hotfix环境

1.对于新项目,如果要启用Hotfix,则直接在框架实体的Hotfix子物体上勾选IsEnableHotfix

2.启用Hotfix之后,点击下面的Create Hotfix Environment按钮便可一键创建Hotfix环境。

3.创建完成后,面板会显示Hotfix环境已成功创建的提示,同时,红色外框标记的便为此项目中Hotfix代码的根目录,之后的Hotfix代码可以按照常规C#代码的方式编写,但必须放在此目录下才会被认为是Hotfix代码。

4.Hotfix环境目录非常简单:

A.Hotfix代码的根目录,新建的Hotfix脚本都必须放在此目录下。

HotfixEnvironment为自动生成的热更新环境类,理论上你不需要改其中任何代码,当然,也支持扩展它。

Hotfix.dll为我们热更的目标库(每次编译后会自动覆盖最新的),发布时只需将之打入指定AB包,并在B面板指定AB包名称及路径。

B.热更目标库打入的AB包名称及路径,如果没有特殊需求,这些可以保持默认值,热更目标库也始终放在A路径下。

创建Hotfix流程

创建完Hotfix环境后,我们直接运行就已经开始执行Hotfix逻辑了,只不过此时的Hotfix库为空,我们需要创建至少一个Hotfix流程(与主框架类似,流程也是Hotfix的生命周期)。

访问权限:Hotfix代码能正常访问外界代码,但任何地方都无法直接访问Hotfix代码,除非用反射!(或者修改一个设定就可以使外界代码直接访问Hotfix代码,但这样就失去了热更新库的可插拨性,丢失了热更新的本质)

推荐使用快捷创建方式:

Project界面右键->Create->HTFramework->C# HotfixProcedure Script

如下,我新建了一个名为Entrance的热更新流程,HotfixProcedureState.Entrance标记表明这是Hotfix逻辑的入口流程:

/// <summary>/// 新建热更新流程/// </summary>[HotfixProcedureState(HotfixProcedureState.Entrance)]public class Entrance : HotfixProcedureBase{/// <summary>/// 流程初始化/// </summary>public override void OnInit(){GlobalTools.LogInfo("初始化 " + typeof(Entrance).Name + " 流程!");}/// <summary>/// 进入流程/// </summary>public override void OnEnter(){GlobalTools.LogInfo("进入 " + typeof(Entrance).Name + " 流程!");}/// <summary>/// 离开流程/// </summary>public override void OnLeave(){GlobalTools.LogInfo("离开 " + typeof(Entrance).Name + " 流程!");}/// <summary>/// 流程帧刷新/// </summary>public override void OnUpdate(){Debug.Log(typeof(Entrance).Name + " 流程更新!");}/// <summary>/// 流程帧刷新(秒)/// </summary>public override void OnUpdateSecond(){}}

在新建一个普通的流程Normal

/// <summary>/// 新建热更新流程/// </summary>[HotfixProcedureState(HotfixProcedureState.Normal)]public class Normal : HotfixProcedureBase{/// <summary>/// 流程初始化/// </summary>public override void OnInit(){GlobalTools.LogInfo("初始化 " + typeof(Normal).Name + " 流程!");}/// <summary>/// 进入流程/// </summary>public override void OnEnter(){GlobalTools.LogInfo("进入 " + typeof(Normal).Name + " 流程!");}/// <summary>/// 离开流程/// </summary>public override void OnLeave(){GlobalTools.LogInfo("离开 " + typeof(Normal).Name + " 流程!");}/// <summary>/// 流程帧刷新/// </summary>public override void OnUpdate(){Debug.Log(typeof(Normal).Name + " 流程更新!");}/// <summary>/// 流程帧刷新(秒)/// </summary>public override void OnUpdateSecond(){}}

我们在入口流程中切换流程:

/// <summary>/// 流程帧刷新/// </summary>public override void OnUpdate(){Debug.Log(typeof(Entrance).Name + " 流程更新!");//鼠标左键双击时切换流程if (Main.m_Input.GetButtonDown(InputButtonType.MouseLeftDoubleClick)){//切换至 Normal 流程HotfixEnvironment.Environment.SwitchProcedure<Normal>();}}

设置资源加载模式

热更新必须使用AssetBundle加载模式,如果没有切换至该模式,将无法初始化热更新环境。

运行

然后我们直接运行场景就可以了,确保勾选了IsEnableHotfix开关,否则将不启用Hotfix逻辑。

接下来我们双击左键,可以看到已经正确的切换了流程:

之后可以在Hotfix流程中扩展自己的代码,以及创建新的流程,不过,发布项目前务必确保最新的Hotfix库已经被打入了AB包中!

Hotfix代码访问外界代码

首先,Hotfix代码可以直接访问框架代码,但无法访问Assembly-CSharp程序集,若要使你的普通业务代码也可以被Hotfix直接访问,可以将你的普通代码统一到一个或多个程序集内,然后添加Hotfix程序集对你的程序集的引用,如下,我建立了一个程序集Test(Create -> Assembly definition),将你的代码全部放在Test所在的文件夹内:

注意:添加了新的程序集后,必须如下标记,将程序集加入到框架的运行时程序域,否则框架将不认识该程序集:

//将 Test 程序集加入框架运行时程序域(可以在任意非编辑器类中定义此字段)[RunTimeAssembly]private static string RuntimeAssembly = "Test";

然后添加Hotfix程序集对Test程序集的引用,之后Hotfix代码便可以无障碍访问Test中的代码:

外界代码访问Hotfix代码

同理,你也可以用如上的方法,添加Test程序集对Hotfix程序集的引用,使Test代码无障碍访问Hotfix代码,不过这样的话你的项目将无法发布,因为Hotfix代码是动态加入的,编辑器切换到RunTime模式后,Test程序集中的代码将找不到Hotfix程序集。

所以外界代码访问Hotfix代码推荐使用反射方式,如下例子:

//【外界代码】//从 Main.m_Hotfix.HotfixAssembly 反射,热更新程序集Type type = Main.m_Hotfix.HotfixAssembly.GetType("HotfixEnvironment");MethodInfo method = type.GetMethod("TestMethod", BindingFlags.Static | BindingFlags.Public);method.Invoke(null, null);//从 Main.m_Hotfix.HotfixEnvironment 反射,热更新环境method = Main.m_Hotfix.HotfixEnvironment.GetType().GetMethod("TestMethod", BindingFlags.Static | BindingFlags.Public);method.Invoke(null, null);

热修复外界方法

Hotfix支持运行时热修复外界任何方法,也即是运行时使用热更新库中的方法,替换外界的任何方法,当在项目上线后某些方法出现了BUG时,便可以在热更新库中修复替换该方法,无需重新发布项目,只需更新Hotfix库即可,待到下次项目版本大更新时,再修复项目中的原方法。

要使用热修复方法功能,外界方法必须在热修复模式下调用:

//【外界代码】public HTFAction OriginalMethodFix;private void OriginalMethod(){GlobalTools.LogInfo("这是原始方法。");}private void Awake(){//使用热修复模式OriginalMethodFix = Main.m_Hotfix.FixMethod(OriginalMethod);//热修复后的方法OriginalMethodFix();}

然后Hotfix代码中用于替换的方法还需要添加一个标记:

//【Hotfix代码】//热修复标记,必须标记目标的完整类名及方法名,中间用.连接[HotfixMethod("TestProcedure.OriginalMethod")]private static void FixMethod(){GlobalTools.LogInfo("这是修复后的方法。");}

使用热修复模式运行方法会有些许消耗,所以可以将修复后的方法保存下来,后面直接使用,当然,当热更新未启用时,使用修复模式运行方法也不会有多余的开销,所以不用担心。

热修复模式支持重载方法:

//【外界代码】private void Awake(){//使用热修复模式Main.m_Hotfix.FixMethod(OriginalMethod)();Main.m_Hotfix.FixMethod<string>(OriginalMethod)("a");Main.m_Hotfix.FixMethod<string, string>(OriginalMethod)("a", "b");}private void OriginalMethod(){GlobalTools.LogInfo("这是原始方法。");}private void OriginalMethod(string arg){GlobalTools.LogInfo("这是原始方法。参数:" + arg);}private void OriginalMethod(string arg1, string arg2){GlobalTools.LogInfo("这是原始方法。参数1:" + arg1 + " 参数2:" + arg2);}

//【Hotfix代码】//热修复标记,必须标记目标的完整类名及方法名,中间用.连接[HotfixMethod("TestProcedure.OriginalMethod")]private static void FixMethod(){GlobalTools.LogInfo("这是修复后的方法。");}[HotfixMethod("TestProcedure.OriginalMethod")]private static void FixMethod(string arg){GlobalTools.LogInfo("这是修复后的方法。参数:" + arg);}[HotfixMethod("TestProcedure.OriginalMethod")]private static void FixMethod(string arg1, string arg2){GlobalTools.LogInfo("这是修复后的方法。参数1:" + arg1 + " 参数2:" + arg2);}

在未启用热更新时,运行:

启用热更新后,运行:

运行时检视面板

在编辑器中运行时将会出现运行时检视面板(Runtime Data),主要用以调试或数据监测,目前面板如下:

1.No Runtime Data!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。