//C# 调用Lua
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
//自定义委托(多个返回数值的函数)
//自定义委托(使用out关键字)
[CSharpCallLua]
public delegate void delAddingMutilReturn(int num1, int num2, out int res1, out int res2, out int res3);
//定义ref 关键字的委托
[CSharpCallLua]
public delegate void delAddingMutilRetRef(ref int num1, ref int num2, out int result);
public class XLuaCallTest : MonoBehaviour {
//XLua的环境核心类(官方建议全局唯一)
LuaEnv env = null;
//自定义委托
public delegate void delAdding(int num1, int num2);
Action act = null;
delAdding act2 = null;
//注意: 以下两种委托定义,需要配置文件支持。
Action act3 = null; //3个参数,没有返回值
Func act4 = null; //第一个int是返回值,后面2个是参数
//委托声明
delAddingMutilReturn act5 = null;
delAddingMutilRetRef act6 = null;
void Start () {
env = new LuaEnv();
env.DoString("require 'CsharpCallLua'");
//c# 调用Lua
//获取一个全局基本数据类型
string str1= env.Global.Get("str");
int num = env.Global.Get("number");
float floNumber = env.Global.Get("floNumber");
bool booFirstTime = env.Global.Get("IsFisrtTime");
//测试结果
Debug.Log("str1=" + str1);
Debug.Log("num=" + num);
Debug.Log("floNumber=" + floNumber);
Debug.Log("booFirstTime=" + booFirstTime);
//------------------------
//访问一个全局table
//方式1: 把table内容映射到普通class或struct,这个过程是值拷贝
//c#修改变量的值,Lua那边的值不变,修改Lua变量的值,c#这边的值也不变
//gameLanguage表名 不要写错
GameLanguage gameLan=env.Global.Get("gameLanguage");
//输出
Debug.Log("gameLan.str1=" + gameLan.str1);
Debug.Log("gameLan.str1=" + gameLan.str2);
Debug.Log("gameLan.str1=" + gameLan.str3);
Debug.Log("gameLan.str1=" + gameLan.str4);
Debug.Log("-------------------" );
//方式2: 映射到一个interface (推荐方式)
// 通过interface映射lua中的表,是一种引用拷贝。
//接口需要添加特性标签[CSharpCallLua],否则无法生成实例代码
//需要生成代码,在unity编辑器菜单 XLua - Generate Code
//得到lua中的表信息
IGameLanguage IgameLan = env.Global.Get("gameLanguage");
//输出显示
Debug.Log("[使用接口]gameLan.str1=" + IgameLan.str1);
Debug.Log("[使用接口]gameLan.str2=" + IgameLan.str2);
Debug.Log("[使用接口]gameLan.str3=" + IgameLan.str3);
Debug.Log("[使用接口]gameLan.str4=" + IgameLan.str4);
//演示接口的引用拷贝原理
IgameLan.str1 = "我是修改后的内容";
env.DoString("print('修改后gameLanguage.str1='..gameLanguage.str1)");
//调用复杂的table
//得到lua中的表信息
IGameUser gameUser = env.Global.Get("gameUser");
//输出显示
Debug.Log("[使用接口]gameLan.ID=" + gameUser.ID);
Debug.Log("[使用接口]gameLan.Name=" + gameUser.name);
Debug.Log("[使用接口]gameLan.Age=" + gameUser.age);
//输出调用方法
gameUser.Speak();
gameUser.Walking();
int tmpResult = gameUser.Calulation(100, 200);
Debug.Log("经过lua中计算,结果= " + tmpResult);
Debug.Log("-------------------");
//方式3: by value方式:映射到Dictionary<>,List<> (适合用在Lua简单表,无法用在复杂表)
//映射到Dictionary
Dictionary dicGameLan=env.Global.Get>("gameLanguage"); //gameLanguage 简单表
foreach(string key in dicGameLan.Keys)
{
Debug.Log("Dic数据 key="+ key+" value= " + dicGameLan[key]);
}
//映射到list
List ListLan = env.Global.Get>("programLanguage");
foreach (string item in ListLan)
{
Debug.Log("programLanguageitem=" + item);
}
Debug.Log("-------------------");
//方式4: by ref方式,映射到LuaTable类。(适合用在一些较为复杂且使用频率很
//低的情况下,一般不推荐使用,因为效率低)
XLua.LuaTable tabGameUser = env.Global.Get("gameUser");
//输出显示
Debug.Log("name=" + tabGameUser.Get("name"));
Debug.Log("Age=" + tabGameUser.Get("age"));
Debug.Log("ID=" + tabGameUser.Get("ID"));
//输出表中函数
XLua.LuaFunction funSpeak = tabGameUser.Get("Speak");
funSpeak.Call();
XLua.LuaFunction funWalking = tabGameUser.Get("Walking");
funWalking.Call();
XLua.LuaFunction funCalulation = tabGameUser.Get("Calulation");
object[] objArray = funCalulation.Call(tabGameUser, 10, 20);
Debug.Log("输出结果=" + objArray[0]);//输出结果: 70
Debug.Log("-------------------");
//-----------------------
//访问一个全局的function
//方式1: 映射到delegate [* 推荐方式]
//注意:
//A: 含有out与ref关键字委托也需要添加特性标签[CSharpCallLua]
//B: 委托引用后,退出luaEnv前,需要释放委托引用,否则lua报错!
//C: 对于Unity与C#中的复杂类型API,必须加入Xlua的配置文件,经过生
//成代码后才能正确应用。 例如:Action 、 Func 等
//得到lua中的函数信息(通过委托来进行映射)
act = env.Global.Get("ProcMyFunc1"); //没有参数,没有返回值
act.Invoke(); //调用
//使用自定义委托调用具备两个输入参数的lua中的函数
//这里要在菜单上XLua-GenerateCode
act2 = env.Global.Get("ProcMyFunc2");
act2(50, 60);
//定义三个输入参数的委托。
//需要配置文件,文件路径在Assets/XLua/Examples/ExampleGenConfig.cs
// 在CSharpCallLua里面写入 typeof(Action),
//还要在菜单上XLua-GenerateCode
act3 = env.Global.Get>("ProcMyFunc4");
act3(20, 30, 40);
//定义具备返回数值,两个输入数值的委托
// Func 第一个int是返回类型
//Func 要加入配置文件ExampleGenConfig
//还要在菜单上XLua-GenerateCode
act4 = env.Global.Get>("ProcMyFunc3");
int intResult = act4(60, 40);
//调用Lua多个返回值的函数
//得到lua中的具有多个返回数值的函数(通过委托out关键字来进行映射)
//要在菜单上XLua-GenerateCode
act5 = env.Global.Get("ProcMyFunc5");
//输出返回结果
int intOutRes1 = 0;
int intOutRes2 = 0;
int intOutRes3 = 0;
act5(100, 880,out intOutRes1, out intOutRes2, out intOutRes3);
Debug.Log(string.Format("res1={0},res2={1},res3={2}", intOutRes1, intOutRes2, intOutRes3));
//得到lua中的具有多个返回数值的函数(通过委托ref关键字来进行映射)
//要在菜单上XLua-GenerateCode
act6 = env.Global.Get("ProcMyFunc5");
//输出返回结果
int intNum1 = 20;
int intNum2 = 30;
int intResult2 = 0;
act6(ref intNum1, ref intNum2, out intResult2);
Debug.Log(string.Format("使用ref关键字,测试多输出 res1={0},res2={1},res3={2}", intNum1, intNum2, intResult2));
//方式2: 映射到LuaFunction (无需生成代码,性能不高)
//得到lua中的函数信息(通过LuaFunction来进行映射)
LuaFunction luaFun = env.Global.Get("ProcMyFunc1");
LuaFunction luaFun2 = env.Global.Get("ProcMyFunc2");
LuaFunction luaFun3 = env.Global.Get("ProcMyFunc3");
//调用具有多返回数值。
LuaFunction luaFun4 = env.Global.Get("ProcMyFunc5");
//输出
luaFun.Call();
luaFun2.Call(10, 20);
object[] objArray2=luaFun3.Call(30, 40);
Debug.Log("调用ProcMyFunc3 ,结果="+ objArray2[0]);
object[] objArray3= luaFun4.Call(22, 80); //多返回数值。
Debug.Log(string.Format("测试多返回数值 res1={0},res2={1},res3={2}", objArray3[0], objArray3[1], objArray3[2]));
}
void OnDestory()
{
act = null;
act2 = null;
act3 = null;
act4 = null;
//释放LuaEnv
env.Dispose();
}
public class GameLanguage
{
public string str1;
public string str2;
public string str3;
public string str4;
}
//定义接口
[CSharpCallLua]
public interface IGameLanguage
{
string str1 { get; set; }
string str2 { get; set; }
string str3 { get; set; }
string str4 { get; set; }
}
//定义接口
[CSharpCallLua]
public interface IGameUser
{
string name { get; set; }
int age { get; set; }
string ID { get; set; }
void Speak();
void Walking();
int Calulation(int num1, int num2);
}
}
Lua文件
CsharpCallLua.lua.txt
--测试Csharp 调用lua
--定义全局变量
str="全局变量"
number=10
local num=20 --测试是否可以调用local 的局部变量
floNumber=88.8
IsFisrtTime=true
--定义一个简单表
gameLanguage={str1="C#语言",str2="lua语言",str3="C++语言",str4="C语言"}
--定义一个综合表(lua中的OOP思想)
gameUser={
name="cuiyong",
age=40,
ID="18011112222",
Speak=function()
print("lua玩家在讨论中")
end,
Walking=function()
print("lua玩家在健身中")
end,
--C#调用Lua的函数时,函数有一个隐藏参数,指向自身
Calulation=function(age,num1,num2)--说明:age 这里命名可以任意,表示当前对象(即:gameUser)
return age.age+num1+num2
end
}
--定义更简单的表
programLanguage={"C#","lua","C++","C"}
--定义单独的lua函数
function ProcMyFunc1()
print("procMyFunc1 无参函数")
end
function ProcMyFunc2(num1,num2)
print("procMyFunc1 两个函数 num1+num2="..num1+num2)
end
function ProcMyFunc3(num1,num2)
print("procMyFunc1 具备返回数值的函数")
return num1+num2
end
function ProcMyFunc4(num1,num2,num3)
print("procMyFunc4 两个函数 num1+num2+num3="..num1+num2+num3)
end
--定义具有多个返回数值的函数
function ProcMyFunc5(num1,num2)
local result=num1+num2
print("ProcMyFunc5 函数,具备返回多个数值")
return num1,num2,result
end