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

推荐订阅源

Vercel News
Vercel News
Recorded Future
Recorded Future
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
The GitHub Blog
The GitHub Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Google DeepMind News
Google DeepMind News
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Microsoft Azure Blog
Microsoft Azure Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
M
MIT News - Artificial intelligence
云风的 BLOG
云风的 BLOG
Y
Y Combinator Blog
N
News | PayPal Newsroom
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Help Net Security
Help Net Security
博客园 - Franky
SecWiki News
SecWiki News
Recent Announcements
Recent Announcements
T
Troy Hunt's Blog
The Register - Security
The Register - Security
The Last Watchdog
The Last Watchdog
Webroot Blog
Webroot Blog
S
Security Affairs
博客园 - 司徒正美
S
Schneier on Security
I
InfoQ
博客园_首页
www.infosecurity-magazine.com
www.infosecurity-magazine.com
T
Threat Research - Cisco Blogs
Forbes - Security
Forbes - Security
腾讯CDC
N
Netflix TechBlog - Medium
N
News and Events Feed by Topic
Cloudbric
Cloudbric
T
The Exploit Database - CXSecurity.com
P
Proofpoint News Feed
A
About on SuperTechFans
Engineering at Meta
Engineering at Meta
Recent Commits to openclaw:main
Recent Commits to openclaw:main
B
Blog
V
Vulnerabilities – Threatpost
C
Check Point Blog
Google DeepMind News
Google DeepMind News
Google Online Security Blog
Google Online Security Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
Hacker News - Newest:
Hacker News - Newest: "LLM"
C
Cisco Blogs
Schneier on Security
Schneier on Security
O
OpenAI News
K
Kaspersky official blog

崎径 其镜

Unity CVE-2025-59489 漏洞修复实践(Google Play 合规) 从零配置 VS Code C++ 环境 力扣笔记 一文详解Hexo 博客搭建 Unity 游戏的 Google Play 16 kb页面对齐处理 Unity 升级到 2022 踩坑记录(URP / 黑屏 / HTTP) Android Google Play 16 KB 页面对齐适配指南 iOS 应用开启包外存储访问(文件共享) Lua新知 EFK日志分析系统的搭建 使用贝塞尔曲线实现道具随机飞动效果 震惊,JS不加分号会造成错误!? Linux升级Python Github图床工具 JS使用replace()函数全部替换 JS使用Splice()函数操作数组 当你的程序连接Mysql然后崩溃时 安卓应用闪屏 安卓各渠道SDK接入体验 某微信爬虫工具多开方案 U3D问题总结(七) lua U3D问题总结(六) 优化 U3D问题总结(五) 渲染与光照 U3D问题总结(四) 物理相关 U3D问题总结(三) Unity基础
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)