Unity3d中使用Lua


對於手機游戲,如果可以在線更新以實現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新手,這種做法也不知是否合理,或者有更簡便的實現方法,請指教。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM