Unity 热更新之ULua 踩坑篇

Unity 的原生c#是无法在移动端上进行热更新的,那么如果线上发布遇到重大闪退事故的话,那么就不可以通过游戏内的热更新进行bug修复,只能重新提交版本,而往往在提交版本到发布的时间内,必然有玩家遇到这种问题,导致流失的,对于团队来说,这个可是很严重的。

所以我google了下,目前已经有开发者实现了这一功能,有c#Light ,ULua,Nlua等,lua在cocos上可以说是非常成功的,与C/C++强大的交互能力,小巧高速的能力,在C/C++上体现的非常好。

最近开始搞Unity,学习了下ULua(ULua,资料),撇开Luajit 64位的坑。首先,打开ulua_v1.08.unitypackage,导入Ulua,如图:

uLua文件夹中 包含一些例子,还有LuaInterface的文档,可以学习学习。

导入成功之后,我们新建一个文件夹Scripts,新建一个Lua文件

void Start(){mgr = new LuaScriptMgr ();mgr.Start ();mgr.DoFile ("LuaEnterance.lua");}

运行doFile函数的时候获取文件的路径通过

LuaDLL.lua_pushstdcallcfunction(L,tracebackFunction);int oldTop=LuaDLL.lua_gettop(L);// Load with Unity3D resourcesbyte[] text = LuaStatic.Load(fileName);

用的是deletage,类似于c++的函数指针

public delegate byte[] ReadLuaFile(string name);public static class LuaStatic{public static ReadLuaFile Load = null;//private static int trace = 0;static LuaStatic(){Load = DefaultLoader;}static byte[] DefaultLoader(string name){byte[] str = null;string path = Util.LuaPath(name);using (FileStream file = new FileStream(path, FileMode.Open)){str = new byte[(int)file.Length];file.Read(str, 0, str.Length);file.Close();}return str;}

然后为了获取准确路径,调用Util.LuaPath,

/// <summary>/// 取得Lua路径/// </summary>public static string LuaPath(string name) {string path = Application.dataPath + "/";string lowerName = name.ToLower();if (lowerName.EndsWith(".lua")) {return path + "lua/" + name;}return path + "lua/" + name + ".lua";}

最后我发现doFile总是会到lua文件夹去找lua文件,这也太不自由了。当然我想到了其他可能性,或许作者为ulua打包做了处理,lua文件夹的文件有特别的好处?或者跟unity的机制有些关系?目前尚不清楚。

不考虑这些情况,我们可以简单做个处理。

void Start(){mgr = new LuaScriptMgr ();mgr.Start ();mgr.DoFile (ReviseLuaPath("LuaEnterance.lua"));}public void DoLuaFile(string filepath){if (mgr != null)mgr.DoFile (ReviseLuaPath (filepath));elseDebug.Log ("DoLuaFile ERROR! Plz create LuaScriptMgr First");}public string ReviseLuaPath(string path){return "../Scripts/" + path;}然后运行,便发现成功了。。。

之后进行进行下一步,在c#中运行lua中函数,首先在lua文件中定义一个函数

然后在c#中获取它

private LuaFunction funcUpdate ;void Start(){mgr = new LuaScriptMgr ();mgr.Start ();mgr.DoFile (ReviseLuaPath("LuaEnterance.lua"));funcUpdate = mgr.GetLuaFunction ("Update");}然后在update中运行void Update(){if (mgr != null){funcUpdate.Call (Time.deltaTime);}}结果发现什么都没有输出。。。醉了醉了。遇到问题那就查!

推测Update这个函数没有获取到。看一下GetLuaFunction

//会缓存LuaFunctionpublic LuaFunction GetLuaFunction(string name){LuaBase func = null;if (!dict.TryGetValue(name, out func)){IntPtr L = lua.L;int oldTop = LuaDLL.lua_gettop(L);if (PushLuaFunction(L, name)){int reference = LuaDLL.luaL_ref(L, LuaIndexes.LUA_REGISTRYINDEX);func = new LuaFunction(reference, lua);func.name = name;dict.Add(name, func);}else{Debuger.LogWarning("Lua function {0} not exists", name);}LuaDLL.lua_settop(L, oldTop);}else{func.AddRef();}return func as LuaFunction;}每次获取缓存的lua函数,会尝试从> dict中获取,然后这个key则是根据你传入的name而定的,那么问题就来了,不同文件下的同名函数怎么办?因为有些函数是Ulua内置的,都是在_G下的,有时候一不小心就可能命名一致,这里的问题也是因为这个导致的,ulua中自带一个Main.lua的文件,这个lua文件中有一个同名函数Update!!所以我们GetLuaFunction实际获得是这个函数!,因为其先被调用,并存在了dict中!LOOK! LuaScriptMgr中有这么一段 public void Start(){OnBundleLoaded();}void OnBundleLoaded(){DoFile("Golbal.lua");unpackVec3 = GetLuaFunction("Vector3.Get");unpackVec2 = GetLuaFunction("Vector2.Get");unpackVec4 = GetLuaFunction("Vector4.Get");unpackQuat = GetLuaFunction("Quaternion.Get");unpackColor = GetLuaFunction("Color.Get");unpackRay = GetLuaFunction("Ray.Get");packVec3 = GetLuaFunction("Vector3.New");packVec2 = GetLuaFunction("Vector2.New");packVec4 = GetLuaFunction("Vector4.New");packQuat = GetLuaFunction("Quaternion.New");packRaycastHit = GetLuaFunction("Raycast.New");packColor = GetLuaFunction("Color.New");packRay = GetLuaFunction("Ray.New");packTouch = GetLuaFunction("Touch.New");#if !MULTI_STATEtraceback = GetLuaFunction("traceback");#endifDoFile("Main.lua");CallLuaFunction("Main");updateFunc = GetLuaFunction("Update");lateUpdateFunc = GetLuaFunction("LateUpdate");fixedUpdateFunc = GetLuaFunction("FixedUpdate");levelLoaded = GetLuaFunction("OnLevelWasLoaded");}它将一些基本的ulua库文件载入了,同时也运行了Main.lua,所以导致了这个错误。『 不可能 』只存在於蠢人的字典里

Unity 热更新之ULua 踩坑篇

相关文章:

你感兴趣的文章:

标签云: