热更新应用--热补丁Hotfix学习笔记

热更新应用--热补丁Hotfix学习笔记本文介绍了如何在 C 工程中实现 Lua 热更新功能 通过热补丁技术改变原有 C 代码的行为 无需重新编译

一.热补丁简介

  热补丁主要是用于将纯C#工程在不重做的情况下通过打补丁的形式改造成具备lua热更新功能工程,主要是让原来脚本中Start函数和Update函数等函数代码块重定向到lua代码。

二.第一个热补丁

  1.C#代码端:

    1)创建一个脚本,并挂载到游戏中的任意物体上(实际使用过程中一般修改已有脚本,这里测试随意挂载就好)

    2)在脚本中定义好测试用的方法,在Start函数中执行Lua文件(LuaManager类及C#调用lua代码的方式详见xlua学习笔记,LuaManager类在:四.C#调用lua-3.lua解析器管理器)

public class HotfixMain : MonoBehaviour { void Start() { LuaManager.Instance.DoLuaFile("Main"); //调用定义的方法,这些方法被lua中的热补丁重新定义了 Debug.Log(Add(1, 2)); Speak("我很帅"); } //预备给热补丁覆盖的成员方法 public int Add(int a,int b) { return 0; } //预备给热补丁覆盖的静态方法 public static void Speak(string str) { Debug.Log("hahaha"); } }

  2.lua端代码

    1)将lua文件放在LuaManager类能够重定向到的文件夹中,或者添加LuaManager类中的重定向方法使lua文件能被找到,这里放在Assets目录下的Lua文件夹下,LuaManager中已经添加了这个文件的重定向方法。

    2).C#代码调用了Main,所以在文件夹中添加Main.lua这个lua文件,这个文件使lua的主入口文件,相当于C#工程中的Main方法,主要用于执行其他lua文件、定义一些通用全局变量、初始化等。这里Main文件中执行Hotfix1文件,代码就一句:

require("Hotfix1")

    3)Hotfix1.lua文件中定义第一个热补丁的代码,主要调用方法xlu.hotfix重写C#中的方法:

--热补丁 --lua中的热补丁固定写法 --通过xlua的hotfix函数进行热补丁更新,参数是:类名、"函数名",lua函数 --成员方法将self作为第一个参数传入 xlua.hotfix(CS.HotfixMain,"Add",function(self,a,b) return a + b end) --静态方法不需要传入self参数 xlua.hotfix(CS.HotfixMain,"Speak",function(a) print(a) end) --热补丁还需要在Unity脚本中作以下操作 --加特性、加宏、生成代码、hotfix注入 --热补丁缺陷:只要修改了热补丁的代码,都需要重新做hotfix注入

  3.Unity中的操作

    1)加特性:在需要被热补丁更新的C#类前面加上[Hotfix]特性,这里给刚才1中创建的脚本加上特性,其他非mono脚本也是一样的做法:

//加上特性以生成热补丁代码 [Hotfix] public class HotfixMain : MonoBehaviour { void Start() { LuaManager.Instance.DoLuaFile("Main"); //调用定义的方法,这些方法被lua中的热补丁重新定义了 Debug.Log(Add(1, 2)); Speak("我很帅"); } //预备给热补丁覆盖的成员方法 public int Add(int a,int b) { return 0; } //预备给热补丁覆盖的静态方法 public static void Speak(string str) { Debug.Log("hahaha"); } }

    2)加宏:打开Unity中Edit->ProjectSetting

      在Player->otherSetting->Scripting Define Symbols中输入HOTFIX_ENABLE

    3)加宏之后生成代码,XLua选项下Generate Code选项生成代码。注意:加宏成功后XLua选项下会出现Hotfix Inject In Editor选项,这个是hotfix注入使用的选项,如果没有的话说明刚才的宏没有成功加上。

    4)Hotfix Inject In Editor进行hotfix注入,如果报错please install the Tools,将xlua工程源文件中的Tools文件夹拷贝到自己的工程中。注意:不是拷贝到Assets目录下,源工程文件夹中Tools文件夹和Assets文件夹同级,所以将Tools文件夹拷贝到自己的工程文件中和Assets文件夹同级文件夹下而不是Assets目录下(三张图片分别是xlua源文件夹中Tools文件夹所在位置、打开工程所在文件夹、拷贝后在自己的工程中Tools文件夹所在位置):

    5)运行工程

  4.最后:注意每次热补丁的代码修改后,都需要重新生成代码和hotfix注入。

三.hotfix重定向其他内容

  1.多函数替换和构造析构函数热补丁(构造函数和析构函数重定向后原代码逻辑会先执行,再执行lua中重定向的代码逻辑,这一点和其他成员函数及静态函数不同)

//加上特性以生成热补丁代码 [Hotfix] public class HotfixMain : MonoBehaviour { void Start() { LuaManager.Instance.DoLuaFile("Main"); //调用定义的方法,这些方法被lua中的热补丁重新定义了 Debug.Log(Add(1, 2)); Speak("我很帅"); } private void Update() { } //预备给热补丁覆盖的成员方法 public int Add(int a,int b) { return 0; } //预备给热补丁覆盖的静态方法 public static void Speak(string str) { Debug.Log("hahaha"); } } [Hotfix] public class HotfixTest { public HotfixTest() { Debug.Log("HotfixTest构造函数"); } public void Speak(string str) { Debug.Log(str); } ~HotfixTest() { } }
--多函数替换 --将多个函数写成一个表作为参数传入 xlua.hotfix(CS.HotfixMain,{ Update = function(self) print(os.time()) end, Add = function(self,a,b) return a + b end, Speak = function(a) print(a) end }) --构造函数热补丁 xlua.hotfix(CS.HotfixTest,{ --构造函数的热补丁固定写法 [".ctor"] = function() print("Lua热补丁构造函数") end, Speak = function(self,a) print("Lua热补丁Speak函数") end, --析构函数的热补丁固定写法 Finalize = function() print("Lua热补丁析构函数") end })

  2.协程函数替换

[Hotfix] public class HotfixMain : MonoBehaviour { void Start() { LuaManager.Instance.DoLuaFile("Main"); StartCoroutine(TestCoroutine()); } IEnumerator TestCoroutine() { while (true) { yield return new WaitForSeconds(1f); Debug.Log("c#协程打印一次"); } } }
--协程函数替换 --使用协程必须引入xlua.util util = require("xlua.util") xlua.hotfix(CS.HotfixMain,{ TestCoroutine = function(self) return util.cs_generator(function() while true do coroutine.yield(CS.UnityEngine.WaitForSeconds(1)) print("lua热补丁协程函数") end end) end })

  3.索引器和属性替换

[Hotfix] public class HotfixMain : MonoBehaviour { private int[] array = new int[] { 5, 4, 3, 2, 1 }; void Start() { LuaManager.Instance.DoLuaFile("Main"); Debug.Log(this.Age); this.Age = 200; Debug.Log(this[0]); this[2] = 10000; } //定义属性 public int Age { get { return 0; } set { Debug.Log(value); } } //定义索引器 public int this[int index] { get { if (index >= 0 && index < 5) return array[index]; return 0; } set { if (index >= 0 && index < 5) array[index] = value; } } }
xlua.hotfix(CS.HotfixMain,{ --属性热补丁的固定写法 --使用set_属性名替换设置属性的方法,使用get_属性名替换获取属性值的方法 set_Age = function(self,v) print("Lua热补丁设置属性") end, get_Age = function(self) return 10 end, --索引器在类中是唯一的,固定写法和属性类似 --使用set_Item替换索引器的set方法,使用get_Item替换索引器的set方法 get_Item = function(self,index) print("Lua热补丁重定向索引器get") return 1000; end, set_Item = function(self,index,v) print("Lua热补丁重定向索引器set") end })

  4.事件替换

[Hotfix] public class HotfixMain : MonoBehaviour { event UnityAction customEvent; void Start() { LuaManager.Instance.DoLuaFile("Main"); StartCoroutine(EventAddRemove()); } private void Update() { if (customEvent != null) customEvent(); } /// <summary> /// 添加到委托中的函数 /// </summary> private void Test() { Debug.Log("event test running"); } /// <summary> /// 使用协程添加和删除委托函数 /// </summary> /// <returns></returns> private IEnumerator EventAddRemove() { customEvent += Test; yield return new WaitForSeconds(5f); customEvent -= Test; } }
--事件热补丁  xlua.hotfix(CS.HotfixMain,{ --add_事件名 代表添加事件 --remove_事件名 代表移除事件 add_customEvent = function(self,del) print(del) print("添加事件函数") --在添加事件时,不要把传入的委托往事件中存,否则会死循环 --self:customEvent("+",del) end, remove_customEvent = function(self,del) print(del) print("移除事件函数") end })

  5.泛型类替换

[Hotfix] public class HotfixTest2<T> { public void Test(T str) { Debug.Log(str); } }
 void Start() { LuaManager.Instance.DoLuaFile("Main"); new HotfixTest2<string>().Test("movin"); new HotfixTest2<int>().Test(10000); }
--泛型类中泛型T可以变化,所以要一个类型一个类型地替换 --在第一个参数后面加上括号,括号中书写一个类型,代表如果泛型是这个类型时地替换方法 xlua.hotfix(CS.HotfixTest2(CS.System.String),{ Test = function(self,str) print("泛型为string时的热补丁,参数是"..str) end }) xlua.hotfix(CS.HotfixTest2(CS.System.Int32),{ Test = function(self,i) print("泛型为int时的热补丁,参数是"..i) end })

 

    

今天的文章 热更新应用--热补丁Hotfix学习笔记分享到此就结束了,感谢您的阅读。
编程小号
上一篇 2024-12-21 22:30
下一篇 2024-12-21 22:27

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/92259.html