能否从宿主程序执行单个Lua语句?
2014-12-21 10:35:58
收藏:0
阅读:87
评论:2
我正在尝试将基于Lua的脚本系统嵌入我的游戏引擎中。
我希望脚本可以具备阻塞和非阻塞命令,例如:
character.walkTo(24, 359); // 直到角色到达之前一直阻塞
c = 35; // 非阻塞,执行继续进行到下一个语句
由于“walkTo”需要在超过一个执行帧的时间内“活动”,我希望能够从Java主机中逐条运行语句,而不是整个函数。
这是因为真正的多线程是过度的,不需要。如果我只能执行一条语句,并保持执行状态“暂停”直到下一条语句执行,我就可以通过检查主机中的命令是否完成来实现阻止命令,如果完成,继续到下一条语句,否则等待下一个帧迭代。
有没有办法从Java宿主中使用LuaJ(或任何其他Lua api)逐条执行1条语句,或者我必须使用lex和yacc开发自己的脚本引擎?
欢迎任何好主意,谢谢!
点赞
用户1909094
以下是我的准确解决方案:
-- test.lua --
onLookAt = function()
character:walkTo(234, 35)
print("到达了!")
end
-- LuaTest.java --
public static void luaTest() {
Globals g = JsePlatform.standardGlobals();
g.load(new CoroutineLib());
g.set("character", CoerceJavaToLua.coerce(new Character(g)));
g.load(Gdx.files.internal("test.lua").reader(), "test.lua").call();
g.load("co = coroutine.wrap(onLookAt)").call();
g.get("co").call();
try {
// 模拟脚本暂停时经过的时间
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
g.get("co").call();
}
public static class Character{
Globals g;
public Character(Globals g){
this.g = g;
}
public void walkTo(int x, int y) {
System.out.println("开始走路。");
g.yield(LuaValue.NONE);
}
}
-- 输出 --
开始走路。
(2秒后)
到达了!
有一件事情你应该非常小心:
- 如果你想完成这个任务,请不要使用Java的ScriptEngine接口。 ScriptEngine接口不提供获取隐式分配的Globals实例的API,而你需要这个实例来进行yield,而且新建一个Globals实例并使用它进行yield是毫无意义的。
2014-12-24 04:01:17
评论区的留言会收到邮件通知哦~
推荐文章
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
看起来你缺少异步模式。如果在
(24,359)处出现character后,必须执行c=35一次,那么正确的方法是将function() c=35 end作为第三个参数传递给walk方法,你的引擎(执行实际的“走路”)会在适当的时候调用该回调函数。character.walkTo(24, 359, function () c = 35 end)否则,
walk可能会将步行计划安排到引擎中并立即进行 yield,在正确的事件上恢复。在这种情况下,您必须设置脚本工作协程(在主状态中无法 yield)。script = coroutine.wrap(function () character.walkTo(24, 359) -- 将 yield 并留下可调用的全局变量 'script' c = 35 end) script() -- 第一次恢复 -- 在此 script 结束 ... -- 此包装器可以在 Lua 或宿主语言中实现 function character.walkTo(x, y) engine.startActualWalkingTo(x, y) coroutine.yield() -- 委托给主机进行 yield -- coroutine.resume() 将在这里继续运行 end ... -- 引擎代码中的某个位置(这里是伪代码) for event in eventLoop do if character.x == endPoint.x and character.y == endPoint.y then script() -- 在 c=35 处再次恢复 end end您可以随时使用
script=nil取消脚本。yield() 有一些限制,请参阅手册。