xLua中Lua調用C#代碼
? ? ? ? 原因:C#實現的系統,因為Lua可以調用,所以完全可以換成Lua實現,因為Lua可以即時更改,即時運行,所以游戲的代碼邏輯就可以隨時更改。
? ? ? ? 實現和C#相同效果的系統,如何實現?
? ? ? ? ? ? ? ? Lua調用Unity的各種API,從而實現C#開發系統同樣的效果
xLua中C#調用Lua代碼
? ? ? ? 原因:Unity是基于C#語言開發的,所有生命周期函數都是基于C#實現,xLua本身是不存在Unity的相關生命周期函數的。如果希望xLua能夠擁有生命周期函數,那么我們可以實現C#作為Unity原始調用,再使用C#調用Lua對應的方法。
具體代碼示例:
在前幾節提到的使用單例模式的xLuaEnv代碼中添加如下代碼:
//返回Lua環境的全局變量public LuaTable Global{get{return _Env.Global;}}
添加CSharpCallVariable腳本代碼:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;public class CSharpCallVariable : MonoBehaviour
{void Start(){xLuaEnv.Instance.DoString("return require('L2C/CSharpCallVariable')");//Debug.Log(data[0]);//LuaEnv提供了一個成員變量Global,它可以用于C#獲取Lua的全局變量//Global的數據類型是C#實現的LuaTable,LuaTable是xLua實現的C#和Lua中表對應的數據結構//xLua會將Lua中的全局變量以Table的方式全部存儲在Global中//通過運行環境,導出全局變量,類型是LuaTable//LuaTable是C#的數據對象,用于和Lua中的全局變量存儲的table對應LuaTable g = xLuaEnv.Instance.Global;//從Lua中,將全局變量提取出來//參數:Lua中全局變量的名稱//類型:Lua中全局變量的名稱所對應的類型//返回值:變量的值int num = g.Get<int>("num");float rate = g.Get<float>("rate");bool isWoman = g.Get<bool>("isWoman");string name=g.Get<string>("name");Debug.Log("數字:" + num);Debug.Log("浮點數:" + rate);Debug.Log("布爾:" + isWoman);Debug.Log("字符串:" + name);}// Update is called once per framevoid OnDestroy(){xLuaEnv.Instance.Free();}
}
Lua相關代碼如下:
--隱性做了{num=100,rate=99.99,isWoman=false,name="admin"}
num=100
rate=99.99
isWoman=false
name="admin"
?運行測試結果如下:
使用C#代碼調用Lua代碼的函數
相關詳細代碼如下所示:
//C#相關代碼
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;public delegate void Func1();
public delegate void Func2(string name);
public delegate string Func3();
//映射產生時,xLua提示添加的[CSharpCallLua]
public delegate void Func4(out string name, out int id);
public class CSharpCallFunction : MonoBehaviour
{void Start(){xLuaEnv.Instance.DoString("return require('L2C/CSharpCallFunction')");LuaTable g = xLuaEnv.Instance.Global;//Lua的函數,會導出為C#的委托類型Func1 func1=g.Get<Func1>("func1");func1();//向Lua函數傳遞數據Func2 func2 = g.Get<Func2>("func2");func2("admin");//接收Lua函數的返回值Func3 func3=g.Get<Func3>("func3");Debug.Log(func3()+",被C#打印");//Lua多返回值Func4 func4 = g.Get<Func4>("func4");string name;int id;func4(out name,out id);Debug.Log(name + "," + id);}// Update is called once per framevoid OnDestroy(){xLuaEnv.Instance.Free();}
}
--Lua相關代碼
func1=function()print("這是Lua中的func1")
end
func2=function(name)print("這是Lua中的func2,參數是:"..name)
end
--Lua的函數會導出為C#的委托
func3=function()return "這是Lua中的func3"
end
func4=function()return "這是Lua中的func4",100
end
運行效果如圖所示:
使用C#代碼調用Lua代碼的結構體
詳細代碼如下所示:
//C#代碼如下所示
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;public delegate void OneStringParams(string name);
public delegate void TransSelf(LuaTable table);//針對結構體調用后添加
public delegate string OneStringReturn();
[CSharpCallLua]
public delegate void TransMy(LuaCore table);//Lua映射table過來,需要有個結構體進行對應
//Lua的table導出到C#的結構體,可以實現C#運行時無GC
[GCOptimize]
public struct LuaCore
{public int ID;public string Name;public bool IsWoman;public OneStringParams Func1;public OneStringReturn Func2;public TransMy Func3;public TransMy Func4;
}
public class CSharpCallTable : MonoBehaviour
{void Start(){xLuaEnv.Instance.DoString("require('L2C/CSharpCallTable')");//UseLuaTable();UseStruct();}public void UseLuaTable(){LuaTable g = xLuaEnv.Instance.Global;//獲取的是全局變量Core,因為它在Lua中是表,所以取出的是LuaTableLuaTable core = g.Get<LuaTable>("Core");//獲取Name//參數:table中索引名//類型:索引對應值的類型Debug.Log(core.Get<string>("Name"));core.Set<string, string>("Name", "admin");OneStringParams osp = core.Get<OneStringParams>("Func1");osp("admin");//相當于":"調用TransSelf ts = core.Get<TransSelf>("Func4");ts(core);}public void UseStruct(){LuaTable g = xLuaEnv.Instance.Global;//將Lua的table導出為coreLuaCore core=g.Get<LuaCore>("Core");Debug.Log(core.Name);core.Func4(core);}// Update is called once per framevoid OnDestroy(){xLuaEnv.Instance.Free();}
}
--Lua代碼如下所示
Core={}Core.ID=100
Core.Name="root"
Core.IsWoman=falseCore.Func1=function(name)print("這是Core表的Func1函數,接收到C#數據"..name)
endCore.Func2=function()return "這是Core表的Func2函數"
end
Core.Func3=function(self)print("這是Core表的Func3函數,Core表的成員變量Name是"..self.Name)
endfunction Core:Func4()print("這是Core表的Func4函數,Core表的成員變量Name是"..self.Name)
end
當出現以下問題提示添加[CSharpCallLua]解決問題,在代碼中添加后卻依然報錯,可嘗試以下方式解決問題:
按下上圖按鍵后重新運行游戲,報錯即可消失
更多有關于Lua與CS之間相互調用的相關知識:
https://shenjun-coder.github.io/LuaBook
該系列專欄為網課課程筆記,僅用于學習參考。