Xlua的hotfix使用心得
项目在开发时使用的是mono脚本后台。这样在技术选型时选的就是用mono更新dll来热更新。但其实这也不算一种对玩家友好的更新方式因为在更新是要强制重启一下。在工作流方面还有打包时要加密dll,mono内要解密dll。项目上线google play。在2019年8月1日后统一强制要求64位。mono未提供64位版本只能重新选用IL2CPP脚本后台。这时候原来的更新流程就废掉了,选用了Xlua的hotfix。使用方式按照说明文档走就可以:开启ENABLE_HOTFIX,并在打包过程中对dll注入一次。
注入后的dll变成如下(用.Net Reflector查看):
private static DelegateBridge __Hotfix0_OnGraphStart;
public override void OnGraphStart(Playable playable)
{
DelegateBridge bridge = __Hotfix0_OnGraphStart;
if (bridge != null)
{
bridge.__Gen_Delegate_Imp706(this, playable);
}
else
{
this.inverseDuration = 1f / ((float) playable.GetDuration<Playable>());
}
}
如果没有xlua.hotfix过,bridge == null走的还是原来的逻辑流程
这里要说下__Gen_Delegate_Imp706这个。这个在生成的文件DelegateGensBridge.cs中的DelegateBridge类的内部。
public void __Gen_Delegate_Imp706(object p0, UnityEngine.Playables.Playable p1)
{
#if THREAD_SAFE || HOTFIX_ENABLE
lock (luaEnv.luaEnvLock)
{
#endif
// 省略了一些代码
#if THREAD_SAFE || HOTFIX_ENABLE
}
#endif
}
会发现这个类中有很多的这样的__Gen_Delegate_Imp*函数。这个是因为OnGraphStart所在的类配置了[XLua.Hotfix]。Xlua会自动收集里面的所有函数签名生成对应的Delegate。[XLua.Hotfix]建议如下这样配置
[XLua.Hotfix]
public static List<Type> by_property
{
get
{
return from type in Assembly.Load("Assembly-CSharp").GetTypes()
where type.IsPublic
select type).ToList();
}
}
然后就是使用了:
在LuaEnv.cs文件中定义的xlua.hotfix函数中如果调用了
xlua.private_accessible(cs)
就可以在hotfix的函数中访问私有字段、属性、方法了。如果没这句也可以自己主动加:
xlua.private_accessible(CS.AnimationSpeedBehaviour) -- 自己加上这句
xlua.hotfix(CS.AnimationSpeedBehaviour, "OnGraphStart", function(self, playable)
-- 逻辑写在这【self就是这个实例对象】
-- self.private_field
end)
一些经验:
1. 主要调用时的冒号:和点号.的区别。实例对象的成员函数要用冒号,静态函数的用点号。
2. 函数尽量短一些,不然hotfix写一遍也很烦恼。一个函数只做一件事也更符合代码规范。
3. 尽量多的把可能有用的值放到类字段中去,免得以后要去hotfix好几个函数取执行阶段的值。
4. 留一些备用的类。类的各种成员函数,字段(可以用List, Dictionary)也多预留一些,开发新功能时hotfix一下就可以用。
5. 把更多的event设置LuaCallCSharp,因为可能以后要增加监听。
6. 注意执行效率,特别是高频执行的函数。