UE4SS Lua 模组管理函数全解析:RestartCurrentMod / UninstallCurrentMod / RestartMod / UninstallMod 的用法与底层实现

发布时间:2026/10/3 2:24:16
UE4SS Lua 模组管理函数全解析:RestartCurrentMod / UninstallCurrentMod / RestartMod / UninstallMod 的用法与底层实现
游戏开发逆向工程【免费下载链接】RE-UE4SSInjectable LUA scripting system, SDK generator, live property editor and other dumping utilities for UE4/5 games项目地址https://gitcode.com/gh_mirrors/re/RE-UE4SS点击查看免费下载本文是 UE4SSUnreal Engine 4/5 的注入式 Lua 脚本系统官方 Lua API 文档中Mod Management Functions模组管理函数的深度技术指南。这四个全局函数允许 Lua 模组在运行时以编程方式重启或卸载自身或其他模组典型场景包括按下热键后重载某个出错或过期的模组、在版本切换或配置变更后自动重启、以及在退出游戏前按需卸载不再需要的模组。读完本文后你将掌握四个函数的完整签名、参数约束、调用时机与底层排队机制并能直接写出可运行的热键管理脚本。一、函数总览模组管理函数由 UE4SS 在 Lua 模组的全局环境中注册源码位于 UE4SS/src/Mod/LuaMod.cpp。它们的特点是不立即执行卸载/重启而是把操作“排队”到下一个更新周期由 UE4SS 主程序统一处理从而避免在 Lua 执行栈中直接销毁自身造成崩溃。函数名作用对象参数返回值RestartCurrentMod()当前正在运行的 Lua 模组无无UninstallCurrentMod()当前正在运行的 Lua 模组无无RestartMod(mod_name)指定名称的其他模组1 个 string无UninstallMod(mod_name)指定名称的其他模组1 个 string无二、RestartCurrentMod重启当前模组RestartCurrentMod将当前正在运行的模组排队在下一个更新周期执行重启。官方文档给出的典型用法是绑定热键RegisterKeyBind(Key.F5, function() print(Restarting mod...\n) RestartCurrentMod() end)源码实现解析从 UE4SS/src/Mod/LuaMod.cpp 可以看到其实现逻辑m_lua.register_function(RestartCurrentMod, [](const LuaMadeSimple::Lua lua) - int { auto mod get_mod_ref(lua); if (!mod) { lua.throw_error(RestartCurrentMod: Could not get mod reference); } // Use mod ID for safe cross-thread reference ModId mod_id mod-get_id(); UE4SSProgram::get_program().queue_reinstall_mod(mod_id); return 0; });关键点通过ModRef全局变量定位自身get_mod_ref从 Lua 全局环境读取ModRef用户数据UE4SS/src/Mod/LuaMod.cpp。如果该全局变量被覆盖为nil会抛出错误Tried retrieving ModRef global variable but it was nil, please do not override this global。因此切勿在模组脚本中覆盖ModRef全局变量。使用 ModId 而非指针传参源码注释明确指出“Use mod ID for safe cross-thread reference”。因为 Lua 函数可能运行在工作线程直接传指针存在线程安全问题改为传 ID由主程序在事件循环线程内查找真实对象UE4SS/src/UE4SSProgram.cpp。无效 ID 静默忽略若 ID 等于InvalidModIdqueue_reinstall_mod(ModId)直接返回若在事件循环中找不到对应模组则输出一条Warning日志Could not find mod to reinstall with ID: {}。三、UninstallCurrentMod卸载当前模组UninstallCurrentMod将当前模组排队卸载。卸载是彻底性的Lua 状态被销毁所有 hooks 和热键绑定都被移除。官方示例RegisterKeyBind(Key.F6, function() print(Uninstalling mod...\n) UninstallCurrentMod() end)源码实现解析实现见 UE4SS/src/Mod/LuaMod.cpp逻辑与RestartCurrentMod对称——同样是先取ModRef再以 ModId 调用UE4SSProgram::queue_uninstall_mod(mod_id)。底层真正的清理动作发生在LuaMod::uninstall()UE4SS/src/Mod/LuaMod.cpp它按顺序执行停止异步线程先request_stop()再join()注释明确说明“先停止异步线程再获取互斥锁以避免死锁”异步线程回调在调用ExecuteInGameThread时可能需要同一把锁。触发停止回调fire_on_lua_stop_for_cpp_mods()与fire_on_lua_stop_for_self()让注册了OnLuaStop的代码得以清理自身资源。清除全局回调注册从m_static_construct_object_lua_callbacks、m_process_console_exec_pre/post_callbacks、m_global_command_lua_callbacks、m_custom_event_callbacks、m_load_map_pre/post_callbacks、m_init_game_state_pre/post_callbacks、m_begin_play_pre/post_callbacks、m_call_function_by_name_with_arguments_pre/post_callbacks、m_local_player_exec_pre/post_callbacks、m_script_hook_callbacks等所有静态回调容器中移除该模组。移除该模组注册的全部热键遍历所有输入事件凡是custom_data 1表示绑定来自 Lua且custom_data2指向当前模组的键位全部清除。四、RestartMod按名称重启指定模组RestartMod接受一个字符串参数——要重启的模组名称——并让该模组在下一个更新周期重启。参数说明#类型说明1string要重启的模组名称与模组目录名一致见下文官方示例RegisterKeyBind(Key.F7, function() print(Restarting MyOtherMod...\n) RestartMod(MyOtherMod) end)源码实现解析实现见 UE4SS/src/Mod/LuaMod.cppm_lua.register_function(RestartMod, [](const LuaMadeSimple::Lua lua) - int { std::string error_overload_not_found{R( No overload found for function RestartMod. Overloads: #1: RestartMod(string mod_name))}; if (!lua.is_string()) { lua.throw_error(error_overload_not_found); } UE4SSProgram::get_program().queue_reinstall_mod_by_name(lua.get_string()); return 0; });参数类型校验如果第一个参数不是字符串会抛出错误信息明确指出唯一重载为#1: RestartMod(string mod_name)。按名称查找queue_reinstall_mod_by_name在事件循环中遍历m_mods用dynamic_castLuaMod*过滤出 Lua 模组并以to_string(lua_mod-get_name()) mod_name做精确匹配UE4SS/src/UE4SSProgram.cpp。模组名称必须精确匹配大小写敏感。找不到时的行为若没有任何 Lua 模组的名称与传入字符串匹配输出Warning日志Could not find mod to reinstall: {}函数静默返回不抛出 Lua 错误。名称从哪里来按名称管理的前提是知道准确的模组名。UE4SS 以Mods/目录下的子目录为单位加载 Lua 模组每个模组目录内含Scripts/main.lua见 UE4SS/src/UE4SSProgram.cpp 对main.lua的路径校验。模组名取自目录名mod_path.stem().string()。以仓库自带的示例模组为例见 assets/Mods 目录常用名称包括ActorDumperMod、LineTraceMod、ConsoleCommandsMod、Keybinds、SplitScreenMod等——这也正是下文“高级示例”中使用的三个名字。五、UninstallMod按名称卸载指定模组UninstallMod接受一个字符串参数——要卸载的模组名称。参数说明#类型说明1string要卸载的模组名称官方示例RegisterKeyBind(Key.F8, function() print(Uninstalling MyOtherMod...\n) UninstallMod(MyOtherMod) end)源码实现解析实现见 UE4SS/src/Mod/LuaMod.cpp与RestartMod完全对称先校验参数为字符串再调用UE4SSProgram::queue_uninstall_mod_by_name(lua.get_string())。底层查找逻辑同样为精确名称匹配找不到时输出Warning日志UE4SS/src/UE4SSProgram.cpp。六、高级示例一键批量管理多个模组官方文档提供了一个高级示例创建一张“模组名 → 热键”映射表用循环批量注册带修饰键的热键从而用一个模组集中管理多个其他模组local ModsToManage { {Key Key.ONE, ModName ActorDumperMod}, {Key Key.TWO, ModName LineTraceMod}, {Key Key.THREE, ModName ConsoleCommandsMod}, } for _, entry in ipairs(ModsToManage) do RegisterKeyBind(entry.Key, {ModifierKey.CONTROL, ModifierKey.SHIFT}, function() print(string.format(Restarting %s...\n, entry.ModName)) RestartMod(entry.ModName) end) end该示例涉及的 API 细节RegisterKeyBind的两种重载从 UE4SS/src/Mod/LuaMod.cpp 可见RegisterKeyBind支持#1: RegisterKeyBind(integer key)和#2: RegisterKeyBind(integer key, table modifier_key_integers)。示例使用的是第二种——第一个参数传Key.ONE/Key.TWO/Key.THREE第二个参数传一个包含ModifierKey.CONTROL和ModifierKey.SHIFT的修饰键表。按键必须是 0~255 的整数RegisterKeyBind对第一个参数有范围校验超出uint8_t范围会抛出Parameter #1 for function RegisterKeyBind must be an integer between 0 and 255。示例中Key.ONE、ModifierKey.CONTROL等枚举在 Lua 中就是对应整数。模组名应使用目录名表中三个模组名对应仓库 assets/Mods 下真实存在的示例模组目录ActorDumperMod、LineTraceMod、ConsoleCommandsMod确保示例开箱可跑。回调错误处理按键回调执行时包裹了 try/catch若 Lua 回调抛出异常会输出Error日志而不会导致 UE4SS 崩溃UE4SS/src/Mod/LuaMod.cpp。扩展思路基于同样的模式你可以把RestartMod换成UninstallMod实现“一键卸载”或对当前模组使用RestartCurrentMod/UninstallCurrentMod。需要注意按键回调内调用这些函数只是“排队”实际执行发生在下一个更新周期因此回调本身可以安全返回不会在回调栈中销毁当前 Lua 状态。七、理解背后的“排队-执行”机制所有四个函数的核心设计都是跨线程安全的事件排队。从 UE4SS/src/UE4SSProgram.cpp 可以归纳出统一模式Lua 线程调用 queue_xxx() ├─ 若不在事件循环线程queue_event(闭包) → 事件循环线程稍后重放该调用 └─ 若在事件循环线程直接执行 ├─ 查找到目标 LuaMod按 ID 或按名称 ├─ m_pause_events_processing true // 暂停事件处理以保证安全 ├─ mod-uninstall() // 清理回调、热键、异步线程 ├─ 卸载路径delete_mod(mod) ├─ 重启路径重新构造 LuaMod 并 start_mod() └─ m_pause_events_processing false值得注意的细节重启 卸载 重建queue_reinstall_mod(LuaMod*)UE4SS/src/UE4SSProgram.cpp先保存模组名称与路径然后uninstall()、移除该模组注册的键位unregister_keydown_events_for_lua_mod、delete_mod最后用保存的名称与路径std::make_uniqueLuaMod(...)重建并start_mod()。因此重启后模组是“全新”的 Lua 状态。执行期间暂停事件处理m_pause_events_processing true被设置为“安全屏障”避免卸载/重启过程中事件回调访问半销毁的对象重启路径上还会在恢复处理之前重新开始新模组避免 Lua 报错时热键失效。全量重装的特例queue_reinstall_mods()UE4SS/src/UE4SSProgram.cpp会卸载全部模组再重新setup_mods()、start_cpp_mods()、start_lua_mods()并重放UnrealInit/ProgramStart事件。这套机制同时被 GUI 的“Reload all mods”按钮UE4SS/src/GUI/GUI.cpp和 Lua 调试器界面UE4SS/src/GUI/LuaDebugger.cpp复用——GUI 层对单个模组的重启/卸载操作调用的正是queue_reinstall_mod_by_name/queue_uninstall_mod_by_name这两个底层函数。八、最佳实践与注意事项不要覆盖ModRef全局变量RestartCurrentMod/UninstallCurrentMod依赖它定位当前模组覆盖会导致错误。按名称管理时名称必须精确匹配RestartMod/UninstallMod的匹配是大小写敏感的精确字符串比较对模组目录名传入错误名称只会得到警告日志不会报错。这些函数是“排队”而非“立即”执行不要依赖返回值或假设调用返回时操作已完成如果需要连续执行多个管理操作建议分散到不同周期或先RestartMod再在下一周期验证。卸载是彻底的UninstallCurrentMod/UninstallMod会销毁 Lua 状态、移除该模组注册的全部 hooks 与热键卸载后该模组的main.lua不会自动重新加载除非再次手动启动或重启 UE4SS。推荐与热键组合使用官方文档的全部示例均以RegisterKeyBind呈现这是运行时管理模组最自然的方式也可在自定义 Lua 全局函数或延迟动作中调用参见 docs/lua-api/global-functions/delayedactions.md 中的相关机制。九、相关文档导航官方 Lua API 总览docs/lua-api.md模组对象与生命周期 APIdocs/lua-api/classes/mod.md全局函数RegisterKeyBind的完整签名可参考 UE4SS/src/Mod/LuaMod.cpp 中的重载声明仓库内置的示例 Lua 模组见 assets/Mods 目录可作为按名称管理时的命名参考。赞分享游戏开发逆向工程【免费下载链接】RE-UE4SSInjectable LUA scripting system, SDK generator, live property editor and other dumping utilities for UE4/5 games项目地址https://gitcode.com/gh_mirrors/re/RE-UE4SS点击查看免费下载相关推荐UE4SS 全局函数 GetMainModThreadId 详解获取 Lua 主线程 ID 的用法与底层实现UE4SS 全局函数 GetMainModThreadId 详解获取 Lua 主线程 ID 的用法与底层实现 GetMainModThreadId 是 UE4游戏开发逆向工程UE4SS Lua 全局函数 print 详解调试控制台输出、参数处理与底层实现UE4SS Lua 全局函数 print 详解调试控制台输出、参数处理与底层实现 print 是 UE4SS 为 Lua 脚本提供的最基础调试工具用于把字符游戏开发逆向工程RE-UE4SS UClass Lua 绑定详解GetCDO 与 IsChildOf 的用法及底层实现RE UE4SS UClass Lua 绑定详解GetCDO 与 IsChildOf 的用法及底层实现 导读 UClass 是虚幻引擎反射系统的核心类型代表游戏开发逆向工程上一篇SourceIO把 Source 引擎模型、贴图和关卡导入 Blender 的实战指南下一篇TypeGraphQL 泛型类型实战用类工厂模式定义可复用的泛型 GraphQL 类型创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考