(XLua)C#與Lua中的交互

XLua下載地址:https://github.com/Tencent/xLua

Paste_Image.png

下載后接下來就是導入XLua到unity里了蓄愁,解析出來的XLua有下面幾個文件夾


Paste_Image.png

我們只需要將Assests:主目錄里面的東西全部導入到Unity里面就OK了竭恬,導入后再XLua的文件夾下有這么幾個戳鹅。里面都有學習的文檔,也可自行去學。


Paste_Image.png
hotfix的環(huán)境配置

在unity的PlayerSetting下的Other Settings里面打開XLua的宏HOTFIX_ENABLE,只有打開這個宏以后才能進行Xlua的修復以及更新

image.png
然后我們打開工程中XLua例子中的第八個例子08_Hotfix看看是如何配置的
image.png

定義后后生成代碼并注入
image.png
如有報錯請看注意事項
使用建議
對所有較大可能變動的類型加上[Hotfix]標識而涉;
建議用反射找出所有函數(shù)參數(shù)、字段瞳秽、屬性瓣履、事件涉及的delegate類型,在C#函數(shù)中調用Lua练俐,在C#函數(shù)上標注[CSharpCallLua]袖迎;
業(yè)務代碼、引擎API腺晾、系統(tǒng)API燕锥,需要在Lua補丁里頭高性能訪問的類型,在Lua中調用C#函數(shù)悯蝉,在C#函數(shù)上標注加上[LuaCallCSharp]归形;
引擎API、系統(tǒng)API可能被代碼剪裁調(C#無引用的地方都會被剪裁)鼻由,如果覺得可能會新增C#代碼之外的API調用连霉,這些API所在的類型要么加LuaCallCSharp,要么加ReflectionUse嗡靡;
開發(fā)過程:
首先開發(fā)業(yè)務代碼->在所有可能出現(xiàn)問題的類上打上hotfix的標簽跺撼,在所有l(wèi)ua調用CSharp的方法上打上LuaCallCSharp,在所有CSharp調用Lua的方法上打上CSharpCallLua->打包發(fā)布->修改bug時只需要更新Lua文件,修改資源時(聲音讨彼,模型歉井,貼圖,圖片哈误,UI)只需要更新ab包哩至。用戶只需要去下載lua文件跟ab包。

C#訪問Lua中的全局變量與table

首先創(chuàng)建一個在Resources下面創(chuàng)建一個文本文件并給其命名為Hello world.lua.txt蜜自,這樣我們就可以讀取到Lua文本文件了菩貌,然后寫入以下

print("hello world from file")
a=100
Str="NiHao"
IsDie=false

person=
{
name="Tao",age=20,

eat=function(self,a,b)     --一個函數(shù) self代表自身  隱藏參數(shù)  后面再跟兩個int參數(shù)
print(a+b)
print("OK")
end
}

接著我們創(chuàng)建一個腳本HolloworldXLua引入程序集XLua在Start方法下寫入

一個LuaEnv實例對應Lua虛擬機,出于開銷的考慮重荠,建議全局唯一
DoString參數(shù)為String箭阶,可輸入任意合法的Lua代碼.

using UnityEngine;
using XLua;

public class HolloworldXLua: MonoBehaviour {

    // Use this for initialization
    void Start () {
        LuaEnv luaenv = new LuaEnv();//一個LuaEnv實例對應Lua虛擬機,出于開銷的考慮戈鲁,建議全局唯一
        luaenv.DoString("require 'Hello world'");//通過內置的Loder加載lua源文件
        int a = luaenv.Global.Get<int>("a");//獲取到Lua里面的全局變量a
        Debug.Log(a);
        string Str = luaenv.Global.Get<string>("Str");
        Debug.Log(Str);
        bool IsDie = luaenv.Global.Get<bool>("IsDie");
        Debug.Log(IsDie);

        //Person p = luaenv.Global.Get<Person>("person");
        IPerson p = luaenv.Global.Get<IPerson>("person");
        Debug.Log(p.name+p.age);
        p.eat(12,22);//調用Lua里面的函數(shù)  p.eat(p,12,22)有隱藏參數(shù)

        luaenv.Dispose();
    }
    class Person
    {
        public string name;
        public int age;  
    }

    //獲取Lua里面的列表用接口也可以映射的仇参,但是要加上CSharpCallLua
    [CSharpCallLua]
    interface IPerson
    {
        string name { get; set; }
        int age { get; set; }
        void eat(int a,int b);
    }

}

在這里訪問Lua中的Table有幾種方法一種是映射到類中,另一種是映射到接口中去婆殿,但是這兩種方法結果都是相同但是诈乒,有一點是不一樣的,那就是映射到類中只拷貝Lua里面的數(shù)據(jù)但是用接口映射的話可以修改Lua里面的數(shù)據(jù).,用接口相當與引用
然后我們就可以看到輸出的結果婆芦,輸出的就是Lua腳本里面的全局變量與里面的table里面的


Paste_Image.png

然后還可以通過Dictionary或者List去映射Lua表里面的數(shù)據(jù)

   void Start()
    {
        LuaEnv luaenv = new LuaEnv();//一個LuaEnv實例對應Lua虛擬機怕磨,出于開銷的考慮喂饥,建議全局唯一
        luaenv.DoString("require 'Hello world'");//通過內置的Loder加載lua源文件

        Dictionary<string, object> dict = luaenv.Global.Get<Dictionary<string, object>>("person");//person表示哪個表
        foreach (string Key in dict.Keys)
        {
            print(Key + ":" + dict[Key]);
        }
        luaenv.Dispose();
    }

輸出結果:


Paste_Image.png

下面使用List也可以映射那些沒有Key的值,
Lua腳本里面

print("hello world from file")
a=100
Str="NiHao"
IsDie=false

person=
{
name="Tao",age=20,2,2,212,15
}
function person:eat(a,b)
   print(a+b)
end 

C#腳本里面

    void Start()
    {
        LuaEnv luaenv = new LuaEnv();//一個LuaEnv實例對應Lua虛擬機,出于開銷的考慮肠鲫,建議全局唯一
        luaenv.DoString("require 'Hello world'");//通過內置的Loder加載lua源文件

  
        List<object> list = luaenv.Global.Get<List<object>>("person");//person表示哪個表
        foreach (object o in list)
        {
            print(o);
        }
        luaenv.Dispose();
    }

最后輸出可以看到2輸出兩次212和15分別輸出一次對應Lua腳本里面的數(shù)據(jù):


Paste_Image.png

還有一種訪問Tab的方式就是使用LuaTable,這種方式不推薦使用仰泻,性能比較慢,我推薦使用第二種方式通過去創(chuàng)建Intaface去映射Lua中的Table滩届。

訪問一個全局的Function

首先Lua腳本里面寫入函數(shù)方法,一個有多個返回值有參數(shù)的方法

function add(a,b)
     print(a+b)
     return a+b,a,b
  end

那么在C#中如何去調用呢下面來看看摘昌,因為我們在C#中只能有一個返回值而在Lua中可以有多個返回值件蚕,那么在C#返回值的時候只能返回第一個值斩披,而Lua后面的返回值可以在C#中用out或者ref去接收后面的返回值

    [CSharpCallLua]
    delegate int Add(int a, int b,out int resa,out int resb);//定義一個有返回值有參數(shù)的委托
    void Start()
       {
        LuaEnv luaenv = new LuaEnv();//一個LuaEnv實例對應Lua虛擬機设褐,出于開銷的考慮,建議全局唯一
        luaenv.DoString("require 'Hello world'");//通過內置的Loder加載lua源文件
        Add add = luaenv.Global.Get<Add>("add");
        int resa, resb;
        int res=add(12,15,out resa,out resb);
        print(res);
        print(resa);
        print(resb);
        add = null;//Action有映射如果直接釋放Lua虛擬機的話直接會報錯只有將Action函數(shù)置空后才能釋放虛擬機
        luaenv.Dispose();
    }

輸出結果,前面兩個是Lua里面輸出的泡挺,后面是C#里面輸出的辈讶,這樣就輕松調用了Lua里面的方法了


Paste_Image.png

還有一種方式就是使用Lua自帶的LuaFction,和上面LuaTable使用一樣比較耗費性能娄猫,但是使用簡單所以這里也不推薦使用

添加自定義Load的方法

如果我們的Lua文本不想放在Resource里面加載想放到其他地方加載怎么辦呢贱除,Xlua也提供了自定義的Load方法,比如我們想把我們的Lua腳本放在StreamingAssets文件夾下面媳溺,那么該如何做呢月幌,首先先在Unity里面創(chuàng)建一個StreamingAssets文件夾,然后把我們的Lua腳本放在StreamingAssets文件夾下悬蔽,創(chuàng)建一個腳本CreateLoade,寫入代碼

    private LuaEnv luaenv;
    // Use this for initialization
    void Start () {
        luaenv = new LuaEnv();

        luaenv.AddLoader(MyLoader);//添加自己的Load

        luaenv.DoString("require 'hello world'");
    }

    private byte[] MyLoader(ref string filePath)
    {
        // Application.streamingAssetsPath表示找到Asses里面的StreamingAssets
        string absPath = Application.streamingAssetsPath + "/" + filePath + ".lua.txt";

        return System.Text.Encoding.UTF8.GetBytes(File.ReadAllText(absPath)); ;
    }

    private void OnDestroy()
    {
        luaenv.Dispose();
    }

然后我們在Unity里面運行起來看結果,輸出了Lua腳本里輸出的結果扯躺。這樣就沒問題了.


Paste_Image.png

在Lua中構造Unity里面游戲物體并且查找游戲對象獲取相應組件

在Lua腳本中寫入

--構造游戲物體,New一個對象
CS.UnityEngine.GameObject("NewByLua")

--訪問靜態(tài)屬性
print(CS.UnityEngine.Time.deltaTime)

--局部變量 訪問Unity里面的游戲物體
local gameobject=CS.UnityEngine.GameObject
local camera=gameobject.Find("Main Camera")
local light=gameobject.Find("Directional Light")
light.name="UpdataLight"

--獲取light游戲物體里面的Light組件 調用成員方法的時候,使用冒號
local lightCom=light:GetComponent("Light")

--銷毀lightCom組件
gameobject.Destroy(lightCom)

這時候C#中構造虛擬機運行的時候就會在Unity里面構造一個空的游戲物體,運行后會生成一個名為NewByLua的空游戲物體蝎困,并且會查找到Directional Light并修改名為為UpdataLight,并移除了里面的Light組件


Paste_Image.png
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末录语,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子禾乘,更是在濱河造成了極大的恐慌澎埠,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件始藕,死亡現(xiàn)場離奇詭異蒲稳,居然都是意外死亡,警方通過查閱死者的電腦和手機鳄虱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門弟塞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人拙已,你說我怎么就攤上這事〈菁剑” “怎么了倍踪?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵系宫,是天一觀的道長。 經(jīng)常有香客問我建车,道長扩借,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任缤至,我火速辦了婚禮潮罪,結果婚禮上,老公的妹妹穿的比我還像新娘领斥。我一直安慰自己嫉到,他們只是感情好,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布月洛。 她就那樣靜靜地躺著何恶,像睡著了一般。 火紅的嫁衣襯著肌膚如雪嚼黔。 梳的紋絲不亂的頭發(fā)上细层,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天,我揣著相機與錄音唬涧,去河邊找鬼疫赎。 笑死,一個胖子當著我的面吹牛碎节,可吹牛的內容都是我干的虚缎。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼钓株,長吁一口氣:“原來是場噩夢啊……” “哼实牡!你這毒婦竟也來了?” 一聲冷哼從身側響起轴合,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤创坞,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后受葛,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體题涨,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年总滩,在試婚紗的時候發(fā)現(xiàn)自己被綠了纲堵。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡闰渔,死狀恐怖席函,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情冈涧,我是刑警寧澤茂附,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布正蛙,位于F島的核電站,受9級特大地震影響营曼,放射性物質發(fā)生泄漏乒验。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一蒂阱、第九天 我趴在偏房一處隱蔽的房頂上張望锻全。 院中可真熱鬧,春花似錦录煤、人聲如沸鳄厌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽部翘。三九已至,卻和暖如春响委,著一層夾襖步出監(jiān)牢的瞬間新思,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工赘风, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留夹囚,地道東北人。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓邀窃,卻偏偏與公主長得像荸哟,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子瞬捕,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內容