资讯动态

UE4SS Lua API 详解:UFunction 调用与函数标志位操作指南

发布时间:2026/10/4 10:29:50 来源:尧图企业网站定制
游戏开发逆向工程【免费下载链接】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点击查看免费下载UFunction是 UE4SS Lua API 中代表 Unreal Engine 反射函数UFUNCTION的类型包装类它在 Lua 侧封装了游戏内函数的调用能力与函数元数据EFunctionFlags的读写能力。本文基于仓库文档 docs/lua-api/classes/ufunction.md 展开并结合 LuaUFunction.cpp 与 LuaUObject.cpp 的源码实现帮助你理解如何通过 UE4SS 在 Lua 中调用任意游戏函数、处理返回值与 Out 参数以及通过函数标志位控制或探测函数行为。读完本文后你将能够在 Lua Mod 中安全地检索并调用反射函数、正确传递调用上下文并读懂与修改 UFunction 的标志位。类型概览与继承关系UFunction继承自UStruct而UStruct又继承自UObject完整继承链见 UStruct 与 UObject 文档。这意味着UFunction天然拥有UObject的全部能力GetFullName()、GetFName()、GetAddress()、GetClass()、IsA()、type()等方法均可直接使用同时也可使用UStruct提供的GetSuperStruct()、ForEachFunction()等反射遍历方法。从源码结构看LuaType::UFunction继承自UObjectBaseUnreal::UFunction, UFunctionName见 LuaUFunction.hpp其底层m_base指针保存着调用该函数时所需的this上下文对象LuaUFunction.hpp。当 UE4SS 通过auto_construct_object发现一个原生对象是UFunction时会自动将其包装为 Lua 侧的 UFunction 对象见 LuaUObject.cpp。在 Types.lua 的 Lua 类型声明Annotation 风格中也给出了与文档一致的 API 骨架---class UFunction : UObject local UFunction {} ---Attempts to call the UFunction ---param ... UFunctionParams function UFunction:__call(...) end ---Returns the flags for the UFunction. ---return integer function UFunction:GetFunctionFlags() end ---Sets the flags for the UFuction. ---param Flags integer function UFunction:SetFunctionFlags(Flags) end调用 UFunction__call 元方法基本用法UFunction通过 Lua 的__call元方法直接调用用法为UFunction(UFunctionParams...)返回类型为auto即“返回值的类型由被调用函数的反射签名决定”。例如local Result SomeUFunction(Param1, Param2)__call元方法在 LuaUFunction.cpp 中注册实际执行逻辑为 LuaUObject.cpp 中的call_ufunction_from_luabase_object.get_metamethods().create(LuaMadeSimple::Lua::MetaMethod::Call, [](const LuaMadeSimple::Lua lua) - int { return call_ufunction_from_lua(lua); });调用上下文calling context的两种来源调用UFunction时UE4SS 需要同时具备两个要素UFunction 本身被调用的函数calling contextthis指针即调用该函数的对象实例。上下文从何而来取决于 UFunction 对象是如何被获取的带上下文获取如果 UFunction 是通过某个UObject的成员访问例如Character:CanJump()中经__index返回的函数则该对象已绑定为上下文直接调用即可。这正是__index文档中强调“记得用冒号:调用”的原因——冒号语法会把Character作为 self 传入UE4SS 借此解析出上下文见 uobject.md。无上下文获取如果 UFunction 是通过StaticFindObject等全局检索方式得到的例如StaticFindObject(/Script/Engine.Default__GameplayStatics)这类用法见 mod.md则必须将UObject上下文作为第一个参数传入即UFunction(ContextUObject, Params...)。源码中的判定逻辑位于 LuaUObject.cpp当首个 userdata 本身就是UFunction时从其绑定的m_base取出上下文否则将第一个 userdata 视为上下文对象并从栈上继续解析出UFunction。若最终两者缺一会抛出错误Tried calling function without both UFunction and calling contextLuaUObject.cpp。参数数量校验与返回值处理调用时 UE4SS 会先根据反射信息计算参数数量并严格校验func-GetNumParms()得到反射参数总数func-GetReturnValueOffset()得到返回值在参数结构体中的偏移当其为0xFFFF时表示无返回值此时GetNumParms()即为真实参数个数否则需减 1 以排除返回值见 LuaUObject.cpp。bool has_return_value return_value_offset ! 0xFFFF; uint8_t num_expected_params_with_return_value has_return_value ? (num_expected_params - 1 0 ? 0 : num_expected_params - 1) : num_expected_params; if (num_supplied_params ! num_expected_params_with_return_value) { lua.throw_error(fmt::format([UFunction::setup_metamethods - __call] UFunction expected {} parameters, received {}, num_expected_params_with_return_value, num_supplied_params)); }如果 Lua 侧提供的参数个数与反射签名不符调用会被拒绝并抛出带期望/实际参数数量的错误避免向游戏进程传入错误的内存布局。参数压栈通过StaticState::m_property_value_pushers中按属性类型注册的 pusher 完成LuaUObject.cpp若遇到未注册处理器的参数类型会报出形如Tried calling UFunction without a registered handler for parameter的错误并给出参数名与类型名。参数填充完毕后通过calling_context-ProcessEvent(func, dynamic_unreal_function_data.data)实际触发游戏内的函数调用LuaUObject.cpp。如果函数有返回值UE4SS 会把它转换为对应的 Lua 值压回栈顶并返回 1 个结果LuaUObject.cpp无返回值时返回 0 个结果。Out 参数引用/输出参数的处理UE4SS 对带CPF_OutParm且非返回值的参数采用“Lua 表回写”机制LuaUObject.cpp调用前Lua 侧需要为每个 Out 参数准备一个 tableUE4SS 用lua.registry().make_ref()保存对该 table 的引用函数调用完成后将 Out 参数的值按参数名写入原 tablelua_table.add_key(param_name)实现引用参数的按名回写LuaUObject.cpp对于数组FArrayProperty、结构体FStructProperty和集合FSetProperty类型的 Out 参数则复用原 table 而非新建reuse_same_table逻辑LuaUObject.cpp。这一设计让 Lua 脚本可以像在原生 C 中一样使用引用参数且回写结果与原参数表保持一致方便后续读取。读取函数标志位GetFunctionFlagsGetFunctionFlags()无参数返回integer即 Unreal 的EFunctionFlags位掩码值。源码实现LuaUFunction.cpp直接将底层UFunction的GetFunctionFlags()结果转为 Lua 整数table.add_pair(GetFunctionFlags, [](const LuaMadeSimple::Lua lua) - int { const auto lua_object lua.get_userdataLuaType::UFunction(); lua.set_integer(lua_object.get_remote_cpp_object()-GetFunctionFlags()); return 1; });示例local Func StaticFindObject(/Script/Engine.Default__GameplayStatics) -- 仅为示意获取路径 -- 假设已通过对象成员访问拿到某个 UFunction local Flags SomeFunction:GetFunctionFlags() print(string.format(Function flags: 0x%X, Flags))EFunctionFlags是 Unreal 引擎定义在Unreal/CoreUObject/UObject/UnrealType.hpp中的位标志枚举常见的标志位包括以引擎定义为准FUNC_Final、FUNC_BlueprintCallable、FUNC_BlueprintEvent、FUNC_Native、FUNC_Event、FUNC_Public、FUNC_Private、FUNC_Protected、FUNC_Static、FUNC_HasOutParms等。通过读取标志位可以在运行时判断一个函数的可见性、是否蓝图可调用、是否为原生函数等元信息。修改函数标志位SetFunctionFlagsSetFunctionFlags(integer Flags)用于直接覆写目标UFunction的标志位。源码实现LuaUFunction.cpp要求第一个参数必须是整数否则抛出UFunction::SetFunctionFlags must have an integer as the first param.的错误随后将 Lua 整数转换为Unreal::EFunctionFlags并写回table.add_pair(SetFunctionFlags, [](const LuaMadeSimple::Lua lua) - int { const auto lua_object lua.get_userdataLuaType::UFunction(); if (!lua.is_integer()) { throw std::runtime_error{UFunction::SetFunctionFlags must have an integer as the first param.}; } auto new_function_flags static_castUnreal::EFunctionFlags(lua.get_integer()); lua_object.get_remote_cpp_object()-GetFunctionFlags() new_function_flags; return 0; });该函数返回 0 个结果无返回值。典型的应用场景包括在调试或逆向分析时临时修改函数的可见性标志以便观察为特定函数追加/移除FUNC_BlueprintCallable等行为标志仅在游戏进程内存中生效重启游戏后恢复原状。注意事项标志位写入是直接的内存级修改会改变游戏进程内该反射函数的行为请确认目标函数与标志组合后再执行不同 UE4/UE5 引擎版本的EFunctionFlags枚举值可能存在差异修改前建议先通过GetFunctionFlags()读取当前值再按位运算构造新值例如Func:SetFunctionFlags(Func:GetFunctionFlags() | 0x00000001)按位或追加标志。实用技巧与调用范式通过 UStruct 遍历查找 UFunction结合UStruct:ForEachFunction(callback)见 ustruct.md可以枚举某个 UClass/UStruct 的全部 UFunction再配合GetFunctionFlags按标志位筛选感兴趣的函数local SomeClass FindFirstOf(SomeClassName) -- 取到任意 UObject 后取其 Class local Class SomeClass:GetClass() Class:ForEachFunction(function(Func) local Flags Func:GetFunctionFlags() -- 例如筛选具有 Out 参数的函数 if bit.band(Flags, 0x00000100) ~ 0 then -- 0x00000100 对应 FUNC_HasOutParms以引擎枚举为准 print(Func:GetFullName()) end return false -- 返回 true 可提前终止遍历 end)注意0x00000100等位值仅作示意实际标志位请以所玩游戏对应 UE 版本的EFunctionFlags枚举定义为准。正确的调用姿势成员函数带上下文Object:FunctionName(Params...)——通过冒号把对象自身作为上下文无上下文函数如StaticFindObject检索结果FunctionName(ContextObject, Params...)——首参必须显式传入调用对象。类型判定若不确定某个对象是否真的是UFunction可用UObject的IsA或type()判定if Obj:IsA(Function) then -- UFunction 的反射类名为 Function -- 安全地按 UFunction 处理 end总结UFunction是 UE4SS Lua API 中与游戏反射函数交互的核心入口调用能力__call元方法 反射参数校验 pusher 机制让 Lua 可以安全调用任意UFunction并正确处理返回值与 Out 参数上下文规则带上下文获取的函数直接调用无上下文如StaticFindObject获取的函数须显式传入第一个UObject参数元数据读写GetFunctionFlags()/SetFunctionFlags(integer)提供对EFunctionFlags的运行时读取与修改。相关实现均可在仓库内继续深入阅读LuaUFunction.cpp、LuaUFunction.hpp、call_ufunction_from_lua所在文件 LuaUObject.cpp以及 Lua 侧的类型声明 Types.lua。赞分享游戏开发逆向工程【免费下载链接】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 Lua 全局函数 StaticFindObject 详解按名称精确检索内存中的 UObjectUClass / UFunctionUE4SS Lua 全局函数 StaticFindObject 详解按名称精确检索内存中的 UObjectUClass / UFunction Stati游戏开发逆向工程RE-UE4SS Lua API 实战RegisterHook 挂钩 UFunction 的完整指南RE UE4SS Lua API 实战RegisterHook 挂钩 UFunction 的完整指南 导读 RegisterHook 是 RE UE4SS 为游戏开发逆向工程UE4SS Lua 全局函数 UnregisterHook 完全指南取消 UFunction Hook 的原理与实战UE4SS Lua 全局函数 UnregisterHook 完全指南取消 UFunction Hook 的原理与实战 UnregisterHook 是 UE4游戏开发逆向工程上一篇获取QQ空间历史说说完整导出所有说说、图片与好友记录下一篇生产环境部署清单S3DirectUpload上线前必做的7项安全检查创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑