柚子快報邀請碼778899分享:筆記 開發(fā)語言 C#調(diào)用Lua
Lua解析器
void Start()
{
//Lua解析器 能夠讓我們在unity中執(zhí)行Lua
//一般情況下 保持它的唯一性
LuaEnv env = new LuaEnv();
//執(zhí)行Lua語言
//一般情況下不會直接用字符串來執(zhí)行l(wèi)ua
env.DoString("print('hello world')", "Lesson1_LuaEnv");//如果報錯了輸出第二個參數(shù)
//執(zhí)行一個Lua腳本 用Lua中的多腳本執(zhí)行命令 require
env.DoString("require('Main')");
//默認(rèn)加載路徑在Resources文件夾下 并且因為在這里
//估計是用Resources.Load加載Lua腳本 只支持.txt .bytes等等
//所以Lua腳本后綴要加txt
//幫助我們清楚Lua中我們沒有手動釋放的對象 相當(dāng)于垃圾回收
//幀更新中定時執(zhí)行 或者 切場景時進行(最好不要每幀都執(zhí)行,垃圾回收消耗性能)
env.Tick();
//銷毀Lua解析器
env.Dispose();
}
文件加載重定向
require函數(shù)會在自定義函數(shù)(如果是多個就依次找)中找文件,如果都找不到再去默認(rèn)路徑(Resources)查找
void Start()
{
LuaEnv env = new LuaEnv();
//xlua提供的一個路徑重定向的方法
//允許我們自定義加載Lua文件的規(guī)則
//當(dāng)我們執(zhí)行Lua語言 require 時 相當(dāng)于執(zhí)行一個lua腳本
//他就會執(zhí)行我們自定義傳入的函數(shù)
env.AddLoader(MyCustomLoader);//但是其實最終我們要在AB包中加載lua文件
env.DoString("require('Main')");
}
//自動執(zhí)行
private byte[] MyCustomLoader(ref string filePath)
{
//通過函數(shù)中的邏輯 去加載 Lua文件
//傳入?yún)?shù)是require執(zhí)行的lua腳本文件名
//拼接一個lua文件所在路徑
string path = Application.dataPath + "/Lua/" + filePath + ".lua";
Debug.Log(path);
//有路徑加載文件
//File 知識點 C#提供的文件讀寫的類
//判斷文件是否存在
if(File.Exists(path))
{
return File.ReadAllBytes(path);
}
else
{
Debug.Log("MyCustomLoader重定向失敗"+filePath);
}
return null;
}
Lua解析器管理器
//Lua解析器
//提供lua解析器
//保證解析器唯一
public class LuaMgr : BaseManager
{
//執(zhí)行Lua語言的函數(shù)dostring
//釋放垃圾 Tick
//銷毀 Dispose
//重定向 AddLoader
//得到Lua中的_G(G表)
private LuaEnv luaEnv;
public LuaTable Global
{
get
{
return luaEnv.Global;
}
}
public void Init()
{
//如果已經(jīng)初始化了 直接返回
if(luaEnv != null)
{
return;
}
else
{
//初始化
luaEnv = new LuaEnv();
//加載lua腳本 重定向
luaEnv.AddLoader(MyCustomLoader);
luaEnv.AddLoader(MyCustomABLoader);
}
}
private byte[] MyCustomLoader(ref string filePath)
{
//通過函數(shù)中的邏輯 去加載 Lua文件
//傳入?yún)?shù)是require執(zhí)行的lua腳本文件名
//拼接一個lua文件所在路徑
string path = Application.dataPath + "/Lua/" + filePath + ".lua";
//有路徑加載文件
//File 知識點 C#提供的文件讀寫的類
//判斷文件是否存在
if (File.Exists(path))
{
return File.ReadAllBytes(path);
}
else
{
Debug.Log("MyCustomLoader重定向失敗" + filePath);
}
return null;
}
//Lua腳本會放在AB包中
//最終要通過加載AB包再夾在其中的Lua校本資源 來執(zhí)行他
//重定向加載AB包中的Lua腳本
private byte[] MyCustomABLoader(ref string filePath)
{
/* Debug.Log("進入AB包加載重定向函數(shù)");
//從AB包中加載lua文件
//加載AB包
string path = Application.streamingAssetsPath + "/lua";
AssetBundle ab = AssetBundle.LoadFromFile(path);
//加載lua文件 返回
TextAsset tx = ab.LoadAsset
//加載出Lua文件的 byte數(shù)組
return tx.bytes;*/
//通過AB包管理器加載lua腳本資源
TextAsset lua = ABMgr.GetInstance().LoadRes
if(lua != null)
{
return lua.bytes;
}
else
{
Debug.Log("MyCustomABLoader重定向失敗" + filePath);
return null;
}
}
//傳入lua文件名 執(zhí)行l(wèi)ua腳本
public void DoLuaFile(string fileName)
{
string str = string.Format("require('{0}')", fileName);
Dostring(str);
}
//Ab包中如果要加載文本 后綴還有一定限制 .lua還是不能被識別
//打包時 要把lua文件后綴改成txt
public void Dostring(string str)
{
if(luaEnv == null)
{
Debug.Log("解析器未初始化");
return;
}
//執(zhí)行Lua語言
luaEnv.DoString(str);
}
public void Tick()
{
if (luaEnv == null)
{
Debug.Log("解析器未初始化");
return;
}
//釋放垃圾
luaEnv.Tick();
}
public void Dispose()
{
if (luaEnv == null)
{
Debug.Log("解析器未初始化");
return;
}
//銷毀解析器
luaEnv.Dispose();
luaEnv = null;
}
}
全局變量的獲取
Main.lua
print("主Lua啟動")
--Unity中寫lua執(zhí)行
--xlua幫我們處理
--只要使執(zhí)行l(wèi)ua腳本 都會自動進入重定向函數(shù)中找文件
require("Test")
Test.lua
print("Test Lua")
testNumber = 1
testBool = true
testFloat = 1.2
testString = "123"
--通過C#沒辦法直接獲取本地變量
local testLocal = 10000
C#
void Start()
{
LuaMgr.GetInstance().Init();
LuaMgr.GetInstance().DoLuaFile("Main");
int l = LuaMgr.GetInstance().Global.Get
print("testNumber" + l);
//使用lua解析器luaenv中的Global屬性
int i = LuaMgr.GetInstance().Global.Get
print("testNumber"+i);
i = 10;//值拷貝 不改變Lua中的值
//改值
LuaMgr.GetInstance().Global.Set("testNumber", 100);
int i2 = LuaMgr.GetInstance().Global.Get
print("testNumber" + i2);
bool b = LuaMgr.GetInstance().Global.Get
print("testBool" + b);
float f = LuaMgr.GetInstance().Global.Get
print("testFloat" + f);
double d = LuaMgr.GetInstance().Global.Get
print("testFloat_Double" + d);
string s = LuaMgr.GetInstance().Global.Get
print("testString" + s);
}
全局函數(shù)的獲取
using System;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Events;
using XLua;
//無參無返回的委托
public delegate void CustomCall();
//有參有返回委托
//該特性在Xlua命名空間中的 要記得在編輯器中生成XLua代碼
[CSharpCallLua]
public delegate int CustomCall2(int a);
[CSharpCallLua]
public delegate int CustomCall3(int a,out int b,out bool c,out string d,out int e);
[CSharpCallLua]
public delegate int CustomCall4(int a, ref int b, ref bool c, ref string d, ref int e);
[CSharpCallLua]
public delegate int CustomCall5(string a, params int[] args); //變長參數(shù)的類型 根據(jù)實際情況來定,最保險的就直接objct
public class Lesson5_CallFunction : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
LuaMgr.GetInstance().Init();
LuaMgr.GetInstance().DoLuaFile("Main");
//無參無返回的獲取
//委托
CustomCall call = LuaMgr.GetInstance().Global.Get
call();
//Unity自帶的委托
UnityAction ua = LuaMgr.GetInstance().Global.Get
ua();
//C#提供的委托
Action ac = LuaMgr.GetInstance().Global.Get
ac();
//Xlua提供的一種函數(shù)獲取方式 (少用 會產(chǎn)生垃圾)
LuaFunction lf = LuaMgr.GetInstance().Global.Get
lf.Call();
//有參有返回
CustomCall2 call2 = LuaMgr.GetInstance().Global.Get
print("有參有返回" + call2(10));
//C#自帶的泛型委托方便我們使用
Func
print("有參有返回" + sFun(20));
//XLua 提供的
LuaFunction lf2 = LuaMgr.GetInstance().Global.Get
print("有參有返回值"+ lf2.Call(30)[0]);
//多返回值
//使用out和ref來接受
CustomCall3 call3 = LuaMgr.GetInstance().Global.Get
int b;
bool c;
string d;
int e;
print("第一個返回值" + call3(100, out b, out c, out d, out e));
print(b + "_" + c + "_" + d + "_" + e);
CustomCall4 call4 = LuaMgr.GetInstance().Global.Get
print("第一個返回值" + call4(200, ref b, ref c, ref d, ref e));
print(b + "_" + c + "_" + d + "_" + e);
//XLua
LuaFunction lf3 = LuaMgr.GetInstance().Global.Get
object[] objs = lf3.Call(1000);
for(int i = 0;i < objs.Length; i++)
{
print("第"+i+"個是"+objs[i]);
}
//變長參數(shù)
CustomCall5 call5 = LuaMgr.GetInstance().Global.Get
call5("123", 1, 2, 3, 4, 5, 6, 77, 8);
//XLua
LuaFunction lf4 = LuaMgr.GetInstance().Global.Get
lf4.Call("456",12,3,4,23,5,34,6,7457);
}
}
testFun =function()
print("無參無返回")
end
--有參有返回
testFun2 =function(a)
print("有參有返回")
return a + 1
end
--多返回
testFun3 =function(a)
print("多返回值")
return 1,2,false,"123",a
end
--變長參數(shù)
testFun4 =function(a,...)
print("變長參數(shù)")
print(a)
arg = {...}
for k,v in pairs(arg) do
print(k,v)
end
end
List和Dictionary映射到table
void Start()
{
LuaMgr.GetInstance().Init();
LuaMgr.GetInstance().DoLuaFile("Main");
//同類型List
List>("testList");
print("****************List****************");
for(int i = 0; i < list.Count; i++)
{
print(list[i]);
}
list[0] = 100;//淺拷貝 不會改變Lua中的內(nèi)容
List>("testList");
print(list2[0]);
//不指定類型 用object來存
List
for (int i = 0; i < list.Count; i++)
{
print(list3[i]);
}
print("****************Dictionary****************");
Dictionary
foreach(string item in dic.Keys)
{
print(item + "_" + dic[item]);
}
dic["1"] = 10000;
Dictionary
print(dic2["1"]);
//淺拷貝 不改變Lua中的內(nèi)容
print("****************Dictionary****************");
Dictionary
foreach (object item in dic3.Keys)
{
print(item + "_" + dic3[item]);
}
}
Test.lua
--List
testList = {1,2,3,4,5}
testList2 = {"123","123",true,1,1.2}
--Dictionary
testDic = {
["1"] = 1,
["2"] = 2,
["3"] = 3,
["4"] = 4
}
testDic2 = {
["1"] = 1,
[true] = 1,
[false] = true,
["123"] = false,
}
類映射table
public class CallLuaClass
{
//在類中聲明成員變量
//名字一定要和Lua那邊的一樣
//一定是公共的 私有和保護無法賦值
//自定義變量中的 變量 可以多也可以少
//如果比Lua中的變量少 就會忽略lua中多的變量
//如果比Lua中的變量多 也不會賦值
public int testInt;
public bool testBool;
public float testFloat;
public string testString;
public CallLuaInClass testInClass;
public UnityAction testFun;
}
public class CallLuaInClass
{
public int testInInt;
}
public class Lesson7_CallClass : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
LuaMgr.GetInstance().Init();
LuaMgr.GetInstance().DoLuaFile("Main");
CallLuaClass obj = LuaMgr.GetInstance().Global.Get
print(obj.testInt);
print(obj.testBool);
print(obj.testFloat);
print(obj.testString);
print("嵌套"+obj.testInClass.testInInt);
obj.testFun();
obj.testInt = 100;
//淺拷貝 不會改變Lua中的值
CallLuaClass obj2 = LuaMgr.GetInstance().Global.Get
print(obj2.testInt);
}
}
--lua中的自定義類
testClass = {
testInt = 2,
testBool = true,
testFloat = 10.2,
testString = "123",
testFun = function()
print("123123")
end,
testInClass = {
testInInt = 5
}
}
接口映射table
//接口中不允許有成員變量
//用屬性來接受
//接口盒類規(guī)則一樣 其中屬性多了少了不影響結(jié)果 多了忽略 少了得不到
[CSharpCallLua]
public interface ICSharpCallInterface
{
int testInt{get; set;}
bool testBool { get; set; }
float testFloat { get; set; }
string testString { get; set; }
UnityAction testFun { get; set; }
}
public class Lesson8_CallInterface : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
LuaMgr.GetInstance().Init();
LuaMgr.GetInstance().DoLuaFile("Main");
ICSharpCallInterface obj = LuaMgr.GetInstance().Global.Get
print(obj.testInt);
print(obj.testBool);
print(obj.testFloat);
print(obj.testString);
obj.testFun();
obj.testInt = 10000;
//接口拷貝 是深拷貝 改變值lua中的值也會改變
ICSharpCallInterface obj2 = LuaMgr.GetInstance().Global.Get
print(obj2.testInt);
}
}
LuaTable映射table
void Start()
{
LuaMgr.GetInstance().Init();
LuaMgr.GetInstance().DoLuaFile("Main");
//不建議使用LuaTable和LuaFunction 因為效率低還會產(chǎn)生垃圾
//引用對象(深拷貝)
LuaTable table = LuaMgr.GetInstance().Global.Get
print(table.Get
print(table.Get
print(table.Get
print(table.Get
table.Get
//改
table.Set("testInt", 10000);
print(table.Get
//深拷貝
LuaTable table2 = LuaMgr.GetInstance().Global.Get
print(table2.Get
//table不用了要記得銷毀 不然會產(chǎn)生垃圾
table.Dispose();
table2.Dispose();
}
注意:
CSharpCallLua特性要在自定義委托和接口前加上
柚子快報邀請碼778899分享:筆記 開發(fā)語言 C#調(diào)用Lua
參考文章
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。