对于手机游戏,如果可以在线更新以实现bug修复、新功能添加等等,其好处自不必多说。
通过C#的反射机制,也可以实现某种程度上的脚本级更新,具体可以参考
http://docs.unity3d.com/Documentation/Manual/scriptsinassetbundles.html
但其中也明确指出了在iOS上不支持反射。所以很自然的,想到使用Lua、Python等脚本语言来解决需求。撇开Python不讲(感兴趣的可以搜索UniPython),来看Lua。
因为Lua本身使用C语言实现,具有良好的跨平台特性,但我们使用C#来作为主要开发语言,要实现与Lua的混合开发,最好是有一个C#版的Lua。万能的google的帮我找到了UniLua(https://github.com/xebecnan/UniLua),特别感谢其作者xebecnan。PS:xebecnan貌似是云风(云风BLOG)团队的,当看到UniLua是国人实现的,且云风的Unity3d项目也在使用时,便立刻决定试一下:)
在现在这个项目之前,几乎没有任何的Lua使用经验,完全是从开始。国内关于Lua的书籍和资料貌似都很少,书的话官方的《Lua程序设计》必读,《Lua游戏开发实践指南》也可以快速翻一翻。个人觉得有用的资源还有:
官方的参考手册-居家旅行必备:http://www.lua.org/manual/5.2/
简明教程 http://coolshell.cn/articles/10739.html
Lua与C++的混合编程入门 http://blog.csdn.net/jason3/article/details/5653487
关于如何在Unity3d中使用UniLua,wiki上面已经讲的非常清晰了。其中也讲到了如何在Lua中调用C#,不过仅给出了调用静态成员函数的示例,而我仅在此记录一下如何在Lua调用C#中的非静态成员函数。
现有C#中的People类如下
1 public class People 2 { 3 public People(int age) 4 { 5 Age = age; 6 } 7 8 public int Age 9 { 10 get; 11 set; 12 } 13 14 public bool IsYounger(People other) 15 { 16 return (Age < other.Age); 17 } 18 }
如何在lua中调用People的成员函数IsYounger?
1. 如何访问C#的对象:使用 light userdata,即使用UniLua提供的 PushLightUserData() 和 ToUserData()
2. 如何访问C#的成员函数:主要是利用PushCSharpFunction() 接口,但过程略麻烦一些。
2.1 将C#类中的成员函数都封装为静态成员函数(后附示例代码)
2.2 将上面的静态成员函数设置为lua的全局变量,以在lua中调用
示例代码:
1 public class PeopleLuaWrapper 2 { 3 const string CLASS_NAME = "People"; 4 5 public static void RegisterCSharpMethod(ILuaState lua) 6 { 7 lua.NewTable(); 8 int method_table = lua.GetTop(); 9 10 lua.PushString("IsYounger"); 11 lua.PushCSharpFunction(IsYounger); 12 lua.SetTable(method_table); //将函数设置为table的一个元素 13 14 lua.SetGlobal(CLASS_NAME); //设置名为CLASS_NAME的全局表 15 } 16 17 //! 将原成员函数重新封装为静态成员函数 18 private static int IsYounger(ILuaState lua) 19 { 20 People invoker = (People)lua.ToUserData(1); //获取成员函数的调用者 21 People other = (People)lua.ToUserData(2); //获取成员函数的参数 22 lua.Pop(2); 23 24 bool is_younger = invoker.IsYounger(other); 25 lua.PushBoolean(is_younger); //将函数结果压栈 26 27 return 1; 28 } 29 }
lua中调用C#成员函数:
1 local function Lua_IsYounger(pa, pb) 2 is_younger = People.IsYounger(pa, pb) 3 return is_younger 4 end 5 6 7 return 8 { 9 Lua_IsYounger = Lua_IsYounger, 10 }
在C#中调用lua代码:
1 ILuaState lua = LuaAPI.NewState(); 2 lua.L_OpenLibs(); 3 4 PeopleLuaWrapper.RegisterCSharpMethod(lua); 5 6 People pa = new People(12); 7 People pb = new People(123); 8 9 var status = lua.L_DoFile("People.lua"); 10 11 lua.GetField(-1, "Lua_IsYounger"); 12 lua.PushLightUserData(pa); 13 lua.PushLightUserData(pb); 14 lua.Call(2, 1); 15 16 bool is_younger = lua.ToBoolean(-1);
示例代码毫无实用意义,但应该足以说明如何实现C#与Lua之间的互相调用。
本人纯粹Lua新手,这种做法也不知是否合理,或者有更简便的实现方法,请指教。