换工作后改做手游需要使用Lua来进行热更新,以前也没接触过Lua,这篇博客算是记录一些学习心得和资料
写这篇博客是接触Lua的第三天,有错误的地方还请大神们指正,Lua语法之类的就不提了,我们从热更新的原理机制开始:
什么是热更新?
为什么要使用Lua进行热更新?
Unity是如何使用Lua进行热更新的?
知乎这个问题的觉得下面已经给出了不少解释,其中一个回答又很好的解释了为什么Unity没有原生的热更新方案,看完这个我又开始疑问编译器和解释器的区别是什么?静态语言和脚本语言的本质区别又是什么?这篇博客给出了非常生形象的解释,然后,我们就可以深入到问题的核心:CIL,大佬也在博客里进行了详细的解释
至此,前两个问题我的理解如下:
1、作为 Unity 游戏来说,热更新即在游戏运行的过程中,编译并运行修改后的新代码
2、因为Ios 通过设置内存 No eXecute 限制了 JIT 的使用,而 Lua 可以通过 AoT 等方式编译运行
第三个问题,目前的方案是SLua, SLua使用起来非常简单方便,但不搞清楚其实现机制,用起来总是会心里没底,而SLua没有完全开源,其源码也少有注释,硬啃源码还是比较吃力
所以,在细究SLua的原理之前,得知道 Lua 和 C/C++ 通常是如何交互的,这篇博客给出了不错的解释,Lua 和 C 交互的核心就是栈,Lua 库也提供了大量 API 用来在 C 中对栈进行操作从而实现 Lua 和 C 的数据交换和函数调用
有了这些前置知识,我们开始看 Slua Unity 的第一个Demo
public class Circle : MonoBehaviour {
LuaSvr svr;
LuaTable self;
LuaFunction update;
[CustomLuaClass]
public delegate void UpdateDelegate(object self);
UpdateDelegate ud;
void Start () {
svr = new LuaSvr();
svr.init(null, () =>
{
self = (LuaTable)svr.start("circle/circle");
update = (LuaFunction)self["update"] ;
ud = update.cast<UpdateDelegate>();
});
}
void Update () {
if (ud != null) ud(self);
}
}
首先是 LuaSvr, LuaSvr 其实是对 Lua_State 的一个封装, 而 Lua_State 在这篇博客有详细的解释,主要是管理一个lua虚拟机的执行环境, 通过名为 L 的 int 指针作为 ref
接下来是 svr.init 其实是将 UnityEngine 的一些常用函数压栈以便接下来在 Lua 中调用,在 Editor 中具体调用如下:
IntPtr L = mainState.L;
LuaObject.init(L);
if (!UnityEditor.EditorApplication.isPlaying)
{
doBind(L);
doinit(mainState, flag);
complete();
mainState.checkTop();
}
LuaObject.init(L)我们先跳过,其中 dobind
static internal void doBind(IntPtr L)
{
var list = collectBindInfo ();
int count = list.Count;
for (int n = 0; n < count; n++)
{
Action<IntPtr> action = list[n];
action(L);
}
}
调用了 list 中所有的委托,现在看看 list 里面存储了什么
static List<Action<IntPtr>> collectBindInfo() {
List<Action<IntPtr>> list = new List<Action<IntPtr>>();
#if !SLUA_STANDALONE
#if !USE_STATIC_BINDER
Assembly[] ams = AppDomain.CurrentDomain.GetAssemblies();
List<Type> bindlist = new List<Type>();
for (int n = 0; n < ams.Length;n++ )
{
Assembly a = ams[n];
Type[] ts = null;
try
{
ts = a.GetExportedTypes();
}
catch
{
continue;
}
for (int k = 0; k < ts.Length; k++)
{
Type t = ts[k];
if (t.IsDefined(typeof(LuaBinderAttribute), false))
{
bindlist.Add(t);
}
}
}
bindlist.Sort(new System.Comparison<Type>((Type a, Type b) => {
LuaBinderAttribute la = System.Attribute.GetCustomAttribute( a, typeof(LuaBinderAttribute) ) as LuaBinderAttribute;
LuaBinderAttribute lb = System.Attribute.GetCustomAttribute( b, typeof(LuaBinderAttribute) ) as LuaBinderAttribute;
return la.order.CompareTo(lb.order);
}));
for (int n = 0; n < bindlist.Count; n++)
{
Type t = bindlist[n];
var sublist = (Action<IntPtr>[])t.GetMethod("GetBindList").Invoke(null, null);
list.

最低0.47元/天 解锁文章
653

被折叠的 条评论
为什么被折叠?



