1、接收全局变量
cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
public class CSharpCallLua : MonoBehaviour
{
void Start()
{
LuaEnv env = new LuaEnv();
env.DoString("require'CSharpCallLua'");
//数据接收 Get<类型>(lua变量名)
//number --- int float double
int a = env.Global.Get<int>("a"); // 获取到Lua 里面的 全局变量 a
string b = env.Global.Get<string>("b");
bool isDie = env.Global.Get<bool>("isDie");
print(a);print(b);print(isDie);
env.Dispose();
}
}
CSharpCallLua.lua.txt
Lua
a= 100
b="jin"
isDie = false
2、访问table类型
方法1:将Table映射到普通的Class类或 Strut结构体
弊端:
- 耗费性能
- 在C#文件中对table的内容进行修改,不会改变lua文件中的值 反之,亦然
可以通过把类型加到GCOptimize生成降低开销
cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
public class CSharpCallLua : MonoBehaviour
{
void Start()
{
LuaEnv env = new LuaEnv();
env.DoString("require'CSharpCallLua'");
//访问table类型
//方法1:将Table映射到普通的Class类或 Strut结构体
Person p= env.Global.Get<Person>("person");
print(p.name + "-" + p.age);
env.Dispose();
}
class Person
{
public string name;
public int age;
}
}
CSharpCallLua.lua.txt
Lua
person= {
name ="jin" ,
age=100
}
方法2:将Table映射到一个interface 接口
易出问题:
interface 要加上特性[CSharpCallLua]
interface 要加上public
如果出现报错:InvalidCastException: This type must add to CSharpCallLua: IPerson
cs
using UnityEngine;
using XLua;
[CSharpCallLua]
public interface IPerson
{
string name { get; set; }
int age { get; set; }
}
public class CSharpCallLua : MonoBehaviour
{
void Start()
{
LuaEnv env = new LuaEnv();
env.DoString("require 'CSharpCallLua'");
// 确保使用 IPerson 接口
IPerson p = env.Global.Get<IPerson>("person");
Debug.Log(p.name + " - " + p.age); // 应输出 "jin - 100"
env.Dispose();
}
}
√ 解决方法:按顺序点击

方法3:更轻量级的by value方式:映射到Dictionary<>,List<>
1)利用Dictionary<> 字典
CSharpCallLua.lua.txt
cs
person= {
name ="jin" ,
age=100,
12,2,2,2,2,"jin",true,3.3,
eat=function(self ,a ,b)
print (a+b)
end
}
CSharpCallLua.cs
cs
using UnityEngine;
using XLua;
public class CSharpCallLua : MonoBehaviour
{
void Start()
{
LuaEnv env = new LuaEnv();
env.DoString("require'CSharpCallLua'");
//Dictionary<> 字典
Dictionary<string,object> dict = env.Global.Get<Dictionary<string, object>>("person");
foreach (var key in dict.Keys)
{
print(key + "-" + dict[key]);
}
env.Dispose();
}
}
- Dictionary<string,object> : 使用object是因为值,什么类型都有
输出结果:
2)利用List<> 字典
CSharpCallLua.cs
cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
public class CSharpCallLua : MonoBehaviour
{
void Start()
{
LuaEnv env = new LuaEnv();
env.DoString("require'CSharpCallLua'");
//List<>列表
List<object> list = env.Global.Get<List<object>>("person");
foreach (var o in list)
{
print(o);
}
env.Dispose();
}
}
输出结果:

List<object> list = env.Global.Get<List<object>>("person"); 改为
List<int> list = env.Global.Get<List<int>>("person");
输出结果:

可以二者结合使用 输出完整的 Table表
方法4:另外一种by ref方式:映射到LuaTable类
LuaTable 是Xlua提供给C# 的一个类,可以得到所有的数据 ,比方法2要慢,没有类型检查
(不常用)
CSharpCallLua.cs
cs
using UnityEngine;
using XLua;
public class CSharpCallLua : MonoBehaviour
{
void Start()
{
LuaEnv env = new LuaEnv();
env.DoString("require'CSharpCallLua'");
//方法4:利用LuaTablefangs
LuaTable tab = env.Global.Get<LuaTable>("person");
print(tab.Get<string>("name"));
print(tab.Get<int>("age"));
env.Dispose();
}
}
输出结果:

3、访问一个全局的function 函数)
方法1:映射到delegate 委托
1)无参版
CSharpCallLua.lua.txt
cs
function add(a,b)
print(a+b)
end
CSharpCallLua.cs
cs
using UnityEngine;
using XLua;
using System;
public class CSharpCallLua : MonoBehaviour
{
void Start()
{
LuaEnv env = new LuaEnv();
env.DoString("require'CSharpCallLua'");
//function
Action<int ,int> act1 = env.Global.Get<Action<int,int>>("add");
act1(36,78);
act1 = null;
//利用委托delegate
Add add = env.Global.Get<Add>("add");
add(12, 78);
add = null;
env.Dispose();
}
// 添加特性 不加报错
[CSharpCallLua]
delegate void Add(int a, int b);
}
输出结果:

报错:InvalidOperationException: try to dispose a LuaEnv with C# callback!
通常是因为在销毁Lua环境(LuaEnv
)时,仍有未释放的C#回调(如委托、事件绑定)残留。
原因:因为C#的GC回收机制导致的,在同一帧
解决方法:利用生命周期
1.OnDisable()
用于可逆操作
- 适合临时释放资源,便于对象重新激活时恢复
- 解绑事件、停止逻辑
2.OnDestroy()
用于不可逆操作
- 确保对象销毁后无残留引用
- 彻底释放资源
代码修改:
cs
using System;
using UnityEngine;
using XLua;
public class CSharpCallLua : MonoBehaviour
{
public LuaEnv env = null; //先声明LuaEnv为公共变量
void Start()
{
LuaEnv env = new LuaEnv();
env.DoString("require'CSharpCallLua'");
//function
Action<int, int> act1 = env.Global.Get<Action<int, int>>("add");
act1(36, 78);
Add add = env.Global.Get<Add>("add");
add(12, 78);
}
//释放资源
private void OnDisable()
{
if (env != null)
{
env.Dispose();
env = null;
}
}
[CSharpCallLua]
delegate void Add(int a, int b);
}
2)有参数
CSharpCallLua.lua.txt
添加return 返回值
Lua
function add(a,b)
print(a+b)
return a+b
end
代码修改:
cs
using System;
using UnityEngine;
using XLua;
//void -> int
//将delegate委托独立出来
[CSharpCallLua]
public delegate int Add(int a, int b);
public class CSharpCallLua : MonoBehaviour
{
public LuaEnv env = null;
void Start()
{
LuaEnv env = new LuaEnv();
env.DoString("require'CSharpCallLua'");
Add add = env.Global.Get<Add>("add");
int res=add(12, 78); //返回值赋值
print(res);
}
private void OnDisable()
{
if (env != null)
{
env.Dispose();
env = null;
}
}
}
如果报错,重复 interface报错问题的解决方法
3)多参数
利用out参数接收多余的数据(ref也可以,但是定义要先赋值 例:int resa=0;)
CSharpCallLua.lua.txt
Lua
function add(a,b)
return a+b,a,b
end
代码修改:
cs
using System;
using UnityEngine;
using XLua;
//在delegate委托中添加out 因为是整数,所以用int类型
[CSharpCallLua]
public delegate int Add(int a, int b,out int resa,out int resb);
public class CSharpCallLua : MonoBehaviour
{
public LuaEnv env = null;
void Start()
{
LuaEnv env = new LuaEnv();
env.DoString("require'CSharpCallLua'");
Add add = env.Global.Get<Add>("add");
//定义resa,resb
int resa; int resb;
int res=add(12, 78,out resa,out resb);
print(res+"_"+resa + "_" + resb);
}
private void OnDisable()
{
if (env != null)
{
env.Dispose();
env = null;
}
}
}
输出结果:

方法2:映射到LuaFuntion
执行慢 ,不推荐
cs
using System;
using UnityEngine;
using XLua;
public class CSharpCallLua : MonoBehaviour
{
public LuaEnv env = null;
void Start()
{
LuaEnv env = new LuaEnv();
env.DoString("require'CSharpCallLua'");
//方法2:映射到LuaFuntion
LuaFunction func = env.Global.Get<LuaFunction>("add");
object[] os= func.Call(1, 2); //因为有多个返回值定义为object[]
foreach (var o in os)
{
print(o);
}
}
private void OnDisable()
{
if (env != null)
{
env.Dispose();
env = null;
}
}
}
输出结果:

建议:
- 不要重复的进行映射(Get)代价较大
- 访问table 使用 interface(建议)
- 访问function 使用 delegate (建议)