xLua热更新4之Hotfix(上篇)

2.8k 词

思考并回答以下问题:

xLua里面有一个热补丁的功能。就是你有的C#代码不用改,就可以加入热更新的功能。

为什么叫热补丁呢?已有项目中的C#代码只需要增加一些配置,不用做其他任何调整就可使用上类似热更新的功能。由于和热更新也不同,所以叫热补丁。这也是xLua首创的一项功能。

热补丁的优点有这些:

  • 侵入性小,老项目原有代码不做任何调整就可使用。
  • 出问题了才用Lua代码来打补丁,这时才会走到lua代码逻辑。运行时影响小,不打补丁基本和原有程序一样。

使用流程

xLua的热补丁使用大体流程如下:

  • 添加HOTFIX_ENABLE宏打开该特性(在Unity3D的File-›Build Setting-›Scripting Define Symbols下添加)。编辑器、各手机平台这个宏要分别设置。如果是自动化打包,要注意在代码里用API设置的宏是不生效的,需要在编辑器设置。

(建议平时开发业务代码不打开HOTFIX_ENABLE,只在build手机版本或者要在编译器下开发补丁时打开HOTFIX_ENABLE)

  • 配置热补丁代码,标识要热更新的类型

  • 执行XLua/Generate Code菜单。

  • 编辑器下开发补丁需要手动执行”XLua/Hotfix Inject In Editor”菜单。打印“hotfix inject finish!”或者“had injected!”才算成功,否则会打印错误信息。发布构建时,这个步骤会自动进行。

如果已经打印了“hotfix inject finish!”或者“had injected!”,执行xlua.hotfix仍然报类似“xlua.access, no field __Hitfix0_Update”的错误,要么是该类没配置到Hotfix列表,要么是注入成功后,又触发了编译,覆盖了注入结果。

注意这个过程会用到xLua中的Tools,需要放到和Assets的同级目录

标识要热更新的类型

和之前学到的xLua配置生成代码类似,有两种方式:

  • 方式一:直接在类里头打Hotfix标签(不建议使用,示例代码只是为了方便演示采取这种方式);

  • 方式二:在一个static类的static字段或者属性里头配置一个列表。属性可以用于实现的比较复杂的配置,比如根据Namespace做白名单。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21

    public static class
    {
    []
    public static List‹Type› by_field = new List‹Type›()
    {
    typeof(HotFixSubClass),
    typeof(GenericClass‹›),
    };

    []
    public static List‹Type› by_property
    {
    get
    {
    return (from type in Assembly.Load("Assembly-CSharp").GetTypes()
    where type.Namespace == "XXXX"
    select type).ToList();
    }
    }
    }

热补丁的限制

  • 不支持静态构造函数。
  • 目前只支持Assets下代码的热补丁,不支持引擎,c#系统库的热补丁。

热补丁Lua API

xlua.hotfix(class, [method_name], fix)

描述 : 注入lua补丁
class : C#类,两种表示方法,CS.Namespace.TypeName或者字符串方式”Namespace.TypeName”,字符串格式和C#的Type.GetType要求一致,如果是内嵌类型(Nested Type)是非Public类型的话,只能用字符串方式表示Namespace.TypeName+NestedTypeName;
method_name : 方法名,可选;
fix : 如果传了method_name,fix将会是一个function,否则通过table提供一组函数。table的组织按key是method_name,value是function的方式。

base(csobj)

描述 : 子类override函数通过base调用父类实现。
csobj : 对象
返回值 : 新对象,可以通过该对象base上的方法
例子:

1
2
3
4
5
xlua.hotfix(CS.BaseTest, 'Foo', function(self, p)
print('BaseTest', p)
base(self):Foo(p)
end)
util.hotfix_ex(class, method_name, fix)

描述 : xlua.hotfix的增强版本,可以在fix函数里头执行原来的函数,缺点是fix的执行会略慢。
method_name : 方法名;
fix : 用来替换C#方法的lua function。

例子

下面来看个简单的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
using UnityEngine;
using XLua;

[]
public class HotfixTest : MonoBehaviour
{
LuaEnv luaenv = new LuaEnv();

private int tick = 0;

// Update is called once per frame
void Update()
{
if (++tick % 50 == 0)
{
Debug.Log("››››››››Update in C#, tick = " + tick);
}
}

void OnGUI()
{
if (GUI.Button(new Rect(10, 10, 300, 80), "Hotfix"))
{
luaenv.DoString(@"
xlua.hotfix(CS.HotfixTest, 'Update', function(self)
self.tick = self.tick + 1
if (self.tick % 50) == 0 then
print('‹‹‹‹‹‹‹‹Update in lua, tick = ' .. self.tick)
end
end)
");
}
}
}

运行这个例子有几步需要注意,其实就是上面学到的热补丁使用流程:

添加 HOTFIX_ENABLE 到 ‘Edit › Project Settings › Player › Other Settings › Scripting Define Symbols’
配置生成代码,这个代码中已经有了
生成代码:执行 ‘XLua › Generate Code’ 菜单,等待Unity编译完成。
注入:执行 ‘XLua › Hotfix Inject In Editor’ 菜单。在编辑器中需要执行,发布时会自动执行。
运行,点击Hotfix按钮查看效果。
这个例子也可以在xLua的XLuaExamples