xLua學習筆記_在C#腳本中使用xLua


  • 目錄 (點擊無法跳轉的那種 ^_^ )
  • 開始
  • 加載Lua文件
  • 在C#腳本中,獲取Lua中的變量
  • 在C#腳本中,獲取Lua中的表
  • 在C#腳本中,獲取Lua中的函數
  • 官方使用建議
  • 自定義Loader加載指定目錄的Lua腳本
  • 待補充....

 

 

 


  • 開始

引入命名空間:

using XLua;

 

 創建Lua的運行環境:

LuaEnv luaenv = new LuaEnv();

這里有一段官方提示:

一個LuaEnv實例對應Lua虛擬機,出於開銷的考慮,建議全局唯一

 

釋放Lua:

luaenv.Dispose();

 


 

  • 加載Lua文件

 注意,當你使用以下方法讀取lua文件的時候

luaenv.DoString("require '文件名'");

這個文件名可以不用添加.lua或者.txt的后綴名,但是!這個文件的后綴名真正其實是.txt! 用.lua作為后綴名,Unity不會識別。

哪能不能不用txt作為后綴呢?

這里貼上一段xLua之FAQ中的一部分:

lua源碼只能以txt后綴?

什么后綴都可以。

如果你想以TextAsset打包到安裝包(比如放到Resources目錄),Unity不認lua后綴,這是Unity的規則。

如果你不打包到安裝包,就沒有后綴的限制:比如自行下載到某個目錄(這也是熱更的正確姿勢),然后通過CustomLoader或者設置package.path去讀這個目錄。

那為啥xLua本身帶的lua源碼(包括示例)為什么都是txt結尾呢?因為xLua本身就一個庫,不含下載功能,也不方便運行時去某個地方下載代碼,通過TextAsset是較簡單的方式。

 


 

  • 在C#腳本中,獲取Lua中的變量

首先,官方給的例子是這個樣子的:

luaenv.Global.Get<int>("a")
luaenv.Global.Get<string>("b")
luaenv.Global.Get<bool>("c")

以上代碼分別獲取了Lua腳本中:

number類型的a       string類型的b       bool類型的c

 

這里需要注意的一點是:在獲取number類型時,一定要注意接收的類型

當Lua中的number類型是小數時,使用Get<int>來獲取會獲取不到該值;返回值為0。

但是使用Get<double>(或者float)來獲取number類型時,無論是整數還是小數,都可以獲取到。

 


 

  • 在C#腳本中,獲取Lua中的表

第一種方法,不推薦,官方描述:

映射到普通class或struct:

要注意的是,這個過程是值拷貝,如果class比較復雜代價會比較大。而且修改class的字段值不會同步到table,反過來也不會。

 方法如下:

1 -- 這是lua中的表
2 table = {
3 name = "xm",age = 12
4 }

需要在C#中定義一個與lua表中的元素名稱,類型一樣,而且必須是public的 (數量可以不一致)的class或者struct;

//這是在C#中定義的類
class MyClass
{
    public string name;
    public int age;
}

准備完畢后調用:

1 MyClass mc = e.Global.Get<MyClass>("table");
2 print(mc.name);
3 print(mc.age);
4 //輸出:
5 //xm
6 //12

使用這種方法時,只能獲取到你在C#類中定義的同名變量,若是你在表中定義了第三個變量,不去獲取;又或是你在C#類中使用了不一樣的名稱變量,去獲取,都不會得到這個值(不一樣名稱會為null),同時也不會報錯。

 

 第二種方法,官方描述:

 映射到一個interface:

這種方式依賴於生成代碼(如果沒生成代碼會拋InvalidCastException異常),代碼生成器會生成這個interface的實例,如果get一個屬性,生成代碼會get對應的table字段,如果set屬性也會設置對應的字段。甚至可以通過interface的方法訪問lua的函數。

定義一個接口,需與lua表中的元素名稱,類型一樣 (數量可以不一致)

注意!這個接口必須是public的,且需要在上面加上[CSharpCallLua] ,並且要在Unity中重新生成xLua代碼         這里有坑,未來補上

 接口:

1 [CSharpCallLua]
2 public interface Itest
3 {
4     string name { get; set; }
5     int age { get; set; }
6 }

調用方法還是和class的差不多:

1 Itest test = luaenv.Global.Get<Itest>("table");
2 Debug.Log(test.name);
3 Debug.Log(test.age);

第二種方法是引用傳遞,在C#中修改值,Lua中也會被修改。

 

 


 

  • 在C#腳本中,獲取Lua中的函數

官方解釋:

這種是建議的方式,性能好很多,而且類型安全。缺點是要生成代碼(如果沒生成代碼會拋InvalidCastException異常)。

可以使用委托的方式:

1 [CSharpCallLua]
2 public delegate void testDelegate(int a,int b,int c,int d);

委托同樣也需要添加[CSharpCallLua]且需要為public,最后需要在Unity中重新生成xLua才可以使用。這兩項缺少一項,都會導致代碼報錯。

 

 調用方法:

1 testDelegate ad = luaenv.Global.Get<testDelegate>("add");
2 ad(1, 2, 3, 4);

Lua方面:

1 function add(a,b,c,d)
2     print(a+b+c+d)
3 end

如果有多個返回值,在定義委托的時候,加上out或者ref關鍵字可達到類似效果:

1 [CSharpCallLua]
2 public delegate void testDelegate(int a,out int o,ref int r);

 

注意:如果直接 luaenv.Dispose() 的話,會報錯:

原因是C#中有變量正在引用着Lua中的東西,需要把C#中的那個變量置空才行。

1 ad = null;

這樣操作后,Dispose就不會報錯了。

 

 

還有一種直接映射到LuaFunction但是性能消耗比上一個要大,用法 及 官方解釋:

1 LuaFunction f = luaenv.Global.Get<LuaFunction>("add");
2 f.Call(1, 2, 3, 4);

這種方式的優缺點剛好和第一種相反。(第一種是 “性能好很多,而且類型安全”)

使用也簡單,LuaFunction上有個變參的Call函數,可以傳任意類型,任意個數的參數,返回值是object的數組,對應於lua的多返回值。

 

 


  •  官方使用建議

結合以上的多種實現方法,官方給出的使用建議:

1、訪問lua全局數據,特別是table以及function,代價比較大,建議盡量少做,比如在初始化時把要調用的lua function獲取一次(映射到delegate)后,保存下來,后續直接調用該delegate即可。table也類似。

2、如果lua測的實現的部分都以delegateinterface的方式提供,使用方可以完全和xLua解耦由一個專門的模塊負責xlua的初始化以及delegateinterface的映射,然后把這些delegateinterface設置到要用到它們的地方。

 


 

  •  自定義Loader加載指定目錄的Lua腳本

設置自定義Loader:

LuaEnv env = new LuaEnv(); env.AddLoader(MyLoader);

 

AddLoader這個函數的參數是一個 返回值為byte類型數組,參數是ref  string類型委托,為方便理解,下面貼出詳細代碼;

紅色字體的MyLoader的定義如下:

1     public byte[] MyLoader (ref string filePath) 2  { 3 //方法體 4 return System.Text.Encoding.UTF8.GetBytes("這里是lua文件的路徑位置"); 5 }



 

 

待補充...


免責聲明!

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



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