0

这是我设置的整体流程:

void ScriptPlayer::new_lua_state() {
   lua = {};
   lua.open_libraries(sol::lib::base, sol::lib::package, sol::lib::coroutine, sol::lib::math);
   
   [...]
   // Proceeds to initialize the state with usertype definitions and values
}

void ScriptPlayer::play(std::string path) {
   main_coroutine = sol::nil;
   script_env = sol::environment(lua, sol::create, lua.globals());
   auto result = lua.load_file(path);
   main_coroutine = sol::coroutine(result);
   script_env.set_on(main_coroutine);
 }

 void ScriptPlayer::update() {
    if (main_coroutine) {
       main_coroutine();
    }
 }

“new_lua_state”在一切开始时被调用一次,然后在我想执行一个新的 lua 脚本(产生)时调用“play”。“更新”每帧执行一次,并推进协程直到完成,此时它停止。

问题: 如果我在前一个脚本协程已经yield但尚未完成时调用“play”,我希望lua丢弃整个环境并创建一个新的,丢弃旧的协程,重新解析脚本,创建一个品牌新的协程并从头开始执行。

相反,我得到的是协程仍然会从前一个脚本协程的状态(应该完全丢弃)而不是从一开始就运行。

这怎么可能?协程的状态究竟存储在哪里?我尝试用线程包装状态,我尝试调用 lua.clear_stack 但没有任何区别,因为当我重新解析脚本并重新创建 sol::协程对象。

任何澄清都非常感谢。

4

1 回答 1

0

这是解决方案: https ://github.com/ThePhD/sol2/issues/1061

显然我用线程包装状态的尝试是错误的,因为这正是要做的事情。

所以为了解决这个问题,这就是我所做的:

void ScriptPlayer::play(std::string path) {
   script_env = sol::nil;
   main_coroutine = sol::nil;

   script_thread = sol::thread::create(lua);
   script_env = sol::environment(script_thread.state(), sol::create, 
   script_thread.state().globals());

   auto result = script_thread.state().load_file(path);
   main_coroutine = sol::coroutine(result);
   script_env.set_on(main_coroutine);
}

仍然让我大吃一惊的是,如果我删除第二行(重置 C 持有的对 lua 协程的引用),结果会返回错误地恢复前一个协程,尽管将相同的变量设置为不同的不久之后的价值..这让我深感困惑。

于 2022-01-12T13:14:56.483 回答