惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Blog — PlanetScale
Blog — PlanetScale
小众软件
小众软件
F
Fortinet All Blogs
博客园 - 叶小钗
博客园_首页
D
DataBreaches.Net
Apple Machine Learning Research
Apple Machine Learning Research
U
Unit 42
爱范儿
爱范儿
aimingoo的专栏
aimingoo的专栏
博客园 - Franky
Martin Fowler
Martin Fowler
酷 壳 – CoolShell
酷 壳 – CoolShell
The Cloudflare Blog
A
About on SuperTechFans
Google DeepMind News
Google DeepMind News
Microsoft Security Blog
Microsoft Security Blog
IT之家
IT之家
M
MIT News - Artificial intelligence
有赞技术团队
有赞技术团队
博客园 - 【当耐特】
S
SegmentFault 最新的问题
Hugging Face - Blog
Hugging Face - Blog

崎径 其镜

Unity 项目迁移鸿蒙(三):SDK 接入 Unity 项目迁移鸿蒙(二):打包与调试 Unity 项目迁移鸿蒙(一):环境准备与工程结构 Unity 项目迁移鸿蒙(一):环境准备与工程结构 阿里云实人认证iOS SDK 升级 阿里云实人认证iOS SDK 升级 DeepSeek V4 Flash 接入 Codex 教程 DeepSeek V4 Flash 接入 Codex 教程 Unity CVE-2025-59489 漏洞修复实践(Google Play 合规) Unity CVE-2025-59489 漏洞修复实践(Google Play 合规) 从零配置 VS Code C++ 环境 从零配置 VS Code C++ 环境 力扣笔记 力扣笔记 一文详解Hexo 博客搭建 一文详解Hexo 博客搭建 Unity 游戏的 Google Play 16 kb页面对齐处理 Unity 升级到 2022 踩坑记录(URP / 黑屏 / HTTP) Unity 升级到 2022 踩坑记录(URP / 黑屏 / HTTP) Android Google Play 16 KB 页面对齐适配指南 Android Google Play 16 KB 页面对齐适配指南 iOS 应用开启包外存储访问(文件共享) iOS 应用开启包外存储访问(文件共享) xlua学习笔记 Lua新知 Lua新知 EFK日志分析系统的搭建 EFK日志分析系统的搭建 使用贝塞尔曲线实现道具随机飞动效果 使用贝塞尔曲线实现道具随机飞动效果
xlua学习笔记
Anqi Zhao · 2021-05-19 · via 崎径 其镜

文件加载

使用LuaEnv中的DoString方法来执行Lua脚本。
因为创建一个LuaEnv相当于创建了一个lua虚拟机,所以一个游戏最好只有一个LuaEnv。


env.DoString("print(\"Hello World\")");


TextAsset ta = Resources.Load<TextAsset>("Lua/helloworld.lua");
env.DoString(ta.text);


env.DoString("require 'Lua/helloworld'");



private byte[] LuaLoader(ref string filePath)
{
string path = "Lua/" + filePath + ".lua";
print(path);
TextAsset ta = Resources.Load<TextAsset>(path);
return System.Text.Encoding.UTF8.GetBytes(ta.text);
}

env.AddLoader(LuaLoader);
env.DoString("require 'helloworld'");

官方建议的加载Lua脚本方式是:整个程序就一个DoString(“require ‘main’”),然后在main.lua加载其它脚本(类似lua脚本的命令行执行:lua main.lua)。

C#访问Lua普通全局变量

先加载lua脚本,再通过LuaEnv.Global.Get获取变量。

TextAsset ta = Resources.Load<TextAsset>("Lua/variable.lua");
env.DoString(ta.text);

int g_int = env.Global.Get<int>("g_int");
string g_str = env.Global.Get<string>("g_str");
bool g_bool = env.Global.Get<bool>("g_bool");

C#访问Lua table的四种方法

需要注意的是,在构建C#中对应的结构时,接口一定要是public修饰,否则会报错。类最好也是,但是经测试,没有报错。

映射到普通class或struct

table的属性可以多于或者少于class的属性,也就是不一定都需要做映射。这个过程是值拷贝,如果class比较复杂代价会比较大。而且修改class的字段值不会同步到table,反过来也不会。

public class Person
{
public string name;
public int age;
}

Person p = env.Global.Get<Person>("g_tbl");

映射到接口

一定要加[CSharpCallLua]和public,否则会报错。

g_int = 1
g_str = "Hello World Variable"
g_bool = false
g_tbl = {name = "Juhnny", age = 12}
g_tbl.say = function(this, str)
print(str)
end
[CSharpCallLua]
public interface IPerson
{
string name { get; set; }
int age { get; set; }
public void say(string str);
}

IPerson p = env.Global.Get<IPerson>("g_tbl");
p.say("Yahoo");

映射到Dictionary和List

这种方法较方法2更为轻量级,但是要求table下key和value类型一致。

g_dic = {apple = "iPhone", flower = "Huawei"}
g_list = {1, 3, 5, 7, 9}
Dictionary<string, string> dic = env.Global.Get<Dictionary<string, string>>("g_dic");
foreach (var child in dic)
{
print(string.Format("Key is {0}, Value is {1}", child.Key, child.Value));
}

List<int> list = env.Global.Get<List<int>>("g_list");
foreach (var v in list)
{
print(v);
}

映射到LuaTable

这种方法比较慢,而且没有类型检查,不推荐使用。

LuaTable tab = env.Global.Get<LuaTable>("g_tbl");
string name = tab.Get<string>("name");
int age = tab.Get<int>("age");
print(string.Format("Name is {0}, age is {1}", name, age));
foreach (string key in tab.GetKeys())
{
print(tab.Get<object>(key));
}

C#访问Lua全局函数

使用delegate映射

这种是建议的方式,性能好很多,而且类型安全,但是要生成代码。支持带返回值,多返回值,甚至返回值都可以是delegate。

g_func1 = function()
print("FF")
end

g_func2 = function(num)
print(num)
return num, "Yoshida", "SE"
end
[CSharpCallLua]
public delegate int Func2(int num, out string name, out string company);



Action func1 = env.Global.Get<Action>("g_func1");
func1();
func1 = null;


Func2 func2 = env.Global.Get<Func2>("g_func2");
int num = func2(14);
func2 = null


Func2 func2 = env.Global.Get<Func2>("g_func2");
string name;
string company;
int num = func2(14, out name, out company);
func2 = null

在过去的一些版本中,需要在不使用后,将接收到的函数销毁,否则会在LuaEnv.Dispose的时候报错。

使用LuaFunction

与上一种方法优缺点相反,不推荐使用。

LuaFunction func = env.Global.Get<LuaFunction>("g_func2");
object[] res = func.Call(14);

Lua调用C#


CS.UnityEngine.Time.deltaTime


CS.UnityEngine.Time.timeScale = 0.5


CS.UnityEngine.GameObject.Find('helloworld')


testobj:DMFunc()

其它注意事项

方法的参数处理
Lua调用侧的参数处理规则:C#的普通参数算一个输入形参,ref修饰的算一个输入形参,out不算,然后从左往右对应lua 调用侧的实参列表。

Lua调用侧的返回值处理规则:C#函数的返回值(如果有的话)算一个返回值,out算一个返回值,ref算一个返回值,然后从左往右对应lua的多返回值。

可变参数的处理


void VariableParamsFunc(int a, params string[] strs)


testobj:VariableParamsFunc(5, 'hello', 'john')

枚举



testobj:EnumTestFunc(CS.Tutorial.TestEnum.E1)

上面的EnumTestFunc函数参数是Tutorial.TestEnum类型的。

枚举类支持__CastFrom方法,可以实现从一个整数或者字符串到枚举值的转换,例如:

CS.Tutorial.TestEnum.__CastFrom(1)
CS.Tutorial.TestEnum.__CastFrom('E1')

委托





testobj:TestEvent('+', lua_event_callback)


testobj:TestEvent('-', lua_event_callback)