Xlua和C#使用简介

本文详细介绍了C#如何通过Xlua调用Lua,包括Lua解析器的创建、字符串加载、全局变量管理和函数获取,以及如何处理LuaTable、LuaFunction、C#类映射、接口映射等,同时涵盖了协程、泛型和系统类型调用等内容。

Xlua

C#调用Lua

lua解析器

lua解析器可以让我们在unity中执行Lua,一般情况下,我们会保证它在unity中的唯一性。

//创建一个lua解析器
LuaEnv env = new LuaEnv();
//执行Lua语言
env.DoString("print('你好世界')");
//像上面这样一句一句的执行lua脚本是非常不好的,所以可以使用lua脚本加载的知识来解决这个问题。
//xlua默认的脚本寻找路径是在Resources文件夹中,但是由于unity并不能识别Lua文件,所以直接加载时会报错的。解决方案是我们将lua后缀多加一个txt,将其转换为文本文件。
env.DoString("require('Main')");
//此方法可以帮助我们清除Lua中我们没有手动释放的对象,相当于垃圾回收。
//我们可以在帧更新中定时执行,也可以在切换场景时执行。
env.Tick();
//销毁Lua解析器,一般会用的会比较少,因为我们之前说过了,我们基本会保证Lua解析器在unity中是全局唯一的。
env.Dispose();

lua文件重定向

//需要调用此方法来添加新的路径,参数为委托类型
//delegate byte[] CustomLoader(ref string filepath)
env.AddLoader(NewLoader);
//这里我们写一个方法并传进去
private byte[] NewLoader(ref string filepath)
{
   
   
    //路径拼接需要加上后缀
    string path = Application.dataPath + "/Lua/" + filepath + ".lua";
    if (File.Exists(path))
    {
   
   
        return File.ReadAllBytes(path);
    }
    return null;
}
//由于委托可以注册多个方法,所以xlua的文件重定向查找方案也是优先查找委托中所有的路径,最后查找默认路径Resources。
//一旦找到对应文件就会返回。不再继续

获取全局变量

//首先我们需要编辑一个test.lua脚本并书写一下信息
print("Test脚本");
testNumber = 1;
testBool = true;
testFloat = 1.2;
testString = "你好";
//在之前的LuaManager中我们添加了一个Global属性,用于获得lua解析器的_G表。
//我们调用xlua的Global中的get方法来获取lua解析器读取的lua脚本中_G表所存放的全局变量。
//注意,字符串内容需要与lua中的变量名一致。
//这里是值拷贝,就算使用临时变量接受了返回值并进行改变也不会影响Lua脚本中的值。
print(LuaManager.GetInstance.Global.Get<int>("testNumber"));
print(LuaManager.GetInstance.Global.Get<bool>("testBool"));
//虽然lua只有一种数值类型number,但是我们可以根据其内容来在C#中为其赋予类型
print(LuaManager.GetInstance.Global.Get<float>("testFloat"));
print(LuaManager.GetInstance.Global.Get<string>("testString"));
//想要改变Lua脚本中的值,我们需要使用Global提供给我们的Set方法。
LuaManager.GetInstance.Global.Set("testNumber",5);
print(LuaManager.GetInstance.Global.Get<int>("testNumber"));

获得全局函数

//我们在test.lua中添加新成员
testFunc1 = function()
	print("这是一个无参无返回值的函数");
end
testFunc2 = function(param)
	print("这是一个有参有返回值的函数");
	return param + 1;
end
testFunc3 = function()
	print("这是一个多返回值的函数");
	return 1,2,"123";
end
testFunc4 = function(...)
	arg = {
   
   ...};
	print("这是一个有变长参数的函数");
	for k,v in pairs(arg) do
		print(k,v)
	end
end
//总的来说,获得lua的全局函数需要使用到委托。
//这里我们可以使用自定义委托,C#提供的标准委托,或是使用Xlua提供的委托。
//注意使用Xlua提供的委托可能发生拆箱装箱
//我们先来看第一种情况,无参无返回值,我们直接使用Action委托来接受。
Action func1 = LuaManager.GetInstance.Global.Get<Action>("testFunc1");
func1.Invoke();
//第二种情况,有参有返回值,我们直接使用Func委托来接受。
 Func<int, int> func2 = LuaManager.GetInstance.Global.Get<Func<int, int>>("testFunc2");
func2.Invoke(10);
//第三种情况,多返回值的函数,我们需要自定义委托来接受。首先我们自定义委托
//当我们要使用自定义委托来接受lua中的全局函数时,我们需要为委托添加[CSharpCallLua]特性,并重新加载。
[CSharpCallLua]
public delegate void FuncHandler(out int paramA,out int paramB, out string paramC);
//使用此委托接受
FuncHandler func3 = LuaManager.GetInstance.Global.Get<FuncHandler>("testFunc3");
int paramA;
int paramB;
string paramC;
func3.Invoke(out paramA,out paramB,out paramC);
//第四种情况,要求输入一个变长参数,我们依旧需要自定义委托来接受。
[CSharpCallLua]
public delegate void FuncHandler2(params object[] array);
FuncHandler2 func4 = LuaManager.GetInstance.Global.Get<
<think>我们正在处理一个关于在XLua中修改C#布尔值的问题。根据提供的引用,特别是引用[3]中展示了C#调用Lua函数获取Lua返回值的例子,我们可以推断出在XLua中,C#Lua之间的数据交互主要是通过委托LuaTable来进行的。 但是,用户的问题是如何在Lua中修改C#的布尔值。这有两种常见情况: 1. 修改C#对象的公共字段或属性(如果是静态的,则修改静态成员)。 2. 通过调用C#的方法来间接修改(例如,设置方法)。 在XLua中,Lua可以访问C#对象的成员,包括字段、属性方法。因此,我们可以通过以下步骤实现: 步骤1:在C#中,确保目标类已经暴露给Lua,并且需要修改的字段或属性是public的(或者通过[LuaCallCSharp]标签标记,使得Lua可以访问)。如果使用属性,那么属性必须具有setter。 步骤2:在Lua中,获取到该C#对象的引用,然后直接给字段或属性赋值(如果是属性,则调用setter)。 示例: 假设我们有一个C#类: ```csharp public class MyClass { public bool myBool = false; public bool MyProperty { get; set; } } ``` 在Lua中,我们可以这样修改: ```lua -- 假设已经获取到了MyClass的实例,比如通过C#传递过来或者从全局获取 local obj = CS.MyClass() -- 创建一个实例(如果类不是静态的) obj.myBool = true -- 修改公共字段 obj.MyProperty = true -- 修改属性 ``` 但是,需要注意的是,如果这个类不是静态类,我们通常需要在C#中创建对象并传递给Lua,或者在Lua中创建对象(如上面所示)。如果对象已经在C#中存在,我们可以通过将对象传递给Lua,或者通过全局变量等方式让Lua获取。 另外,引用[1]中提到,如果使用值类型泛型,在il2cpp下可能有限制,但布尔值不是泛型,所以直接修改布尔值应该没有问题。 因此,具体操作如下: 1. 在C#中,将需要修改的C#对象传递给Lua环境(例如,通过设置Lua的全局变量)。 2. 在Lua中,通过该全局变量获取到C#对象。 3. 然后直接对对象的布尔字段或属性进行赋值。 示例代码(C#): ```csharp public class Test : MonoBehaviour { public bool flag = false; void Start() { LuaEnv luaenv = new LuaEnv(); // 将当前对象(this)传递给Lua,命名为"testObj" luaenv.Global.Set("testObj", this); luaenv.DoString(@" -- 修改C#中的布尔值 testObj.flag = true "); luaenv.Dispose(); Debug.Log(flag); // 输出应该是True } } ``` 注意:上面的例子中,我们在Lua中修改了C#对象的公共字段flag。如果flag是属性,那么需要确保有setter,并且属性是public的。 另外,如果这个布尔值是静态的,那么可以直接通过类名访问: 在C#中: ```csharp public class MyConfig { public static bool IsDebug = false; } ``` 在Lua中: ```lua CS.MyConfig.IsDebug = true ``` 但是,请注意,静态成员在Lua中是通过类名直接访问的。 注意事项: - 确保在C#中,该字段或属性是public的,否则Lua无法访问。 - 如果使用热更新,并且该字段或属性在后续版本中可能被修改,建议使用[Hotfix]标签,或者考虑使用间接方法(如通过方法调用来设置)以增加兼容性。 因此,用户的问题可以通过在Lua中直接对C#对象的字段或属性赋值来解决。 生成相关问题: 1. 在XLua中如何访问C#的静态字段? 2. 如果C#的字段是私有的,如何在XLua中修改? 3. 在XLua中修改C#对象的属性时需要注意什么? 4. XLuaC#的值类型引用类型的处理有什么不同? 5. 在XLua中如何调用C#的方法来修改状态?</think>在 XLua 中修改 C# 的布尔值,可以通过以下两种方式实现(根据引用[3]的示例原理): ### 方法 1:直接修改对象的公共字段 **步骤:** 1. **C# 暴露字段**:确保目标字段是 `public` 的 ```csharp public class Player { public bool isAlive = true; // 公共布尔字段 } ``` 2. **Lua 中修改**: ```lua -- 获取 C# 对象实例 local player = CS.UnityEngine.GameObject.Find("Player"):GetComponent(typeof(CS.Player)) -- 直接修改布尔值 player.isAlive = false -- 修改为 false ``` --- ### 方法 2:通过属性或方法修改 **步骤:** 1. **C# 定义可修改属性**: ```csharp public class GameSettings { private bool _isPaused; public bool IsPaused { // 公共属性 get => _isPaused; set => _isPaused = value; } // 或通过方法修改 public void SetPaused(bool value) => _isPaused = value; } ``` 2. **Lua 中调用**: ```lua local settings = CS.GameSettings.Instance -- 修改属性 settings.IsPaused = true -- 或调用方法 settings:SetPaused(true) ``` --- ### 关键注意事项 1. **字段/属性要求**: - 必须为 `public` 修饰符 - 静态字段使用 `CS.类名.字段名` 访问 2. **值类型处理**: - 布尔值属于值类型,可直接修改(引用[1]中值类型的限制主要针对泛型) 3. **跨语言交互**: - 修改本质是通过 XLua 生成的包装代码完成,类似 `player:set_isAlive(false)`(自动生成)[^3] > 示例:在 Lua 中监控修改结果 > ```lua > print("修改前: " .. tostring(player.isAlive)) > player.isAlive = false > print("修改后: " .. tostring(player.isAlive)) -- 输出 false > ``` --- ### 常见问题排查 1. **修改无效**: - 检查字段是否 `public` - 确认对象实例是否正确获取(非 `null`) 2. **泛型限制**: - 如涉及值类型泛型,需确保 C# 侧已提前调用(引用[1]) ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值