SDK 生成器
此生成器旨在让 C++ Mod 能够方便地访问所有反射成员变量和函数。它还会为所有反射枚举生成 enum 定义。
生成的结构体和类具有准确的内存布局:会输出开头、成员之间及末尾的填充,重现静态数组和位域,并通过计算确定结构体对齐,而非直接假定。
如果派生类型将成员放在基类型的尾部填充区域内(MSVC 允许非 POD 类型这样做),生成器会以紧凑布局输出基类,并显式设置 alignas,使派生成员仍位于正确的偏移位置。
对于生成器无法用 C++ 类型表达的属性——例如 TMap/TSet 成员、Verse 属性,或运行中的引擎定义了但生成器尚不认识的属性类——生成器会在 UE4SS_SDK/PlaceholderTypes.hpp 中用不透明占位类型表示,并采用引擎报告的大小和对齐。成员名称与偏移得以保留,其后所有内容仍保持正确位置;如果你自行编写了类型定义,可用 GetTyped<T>() 将这块存储重新解释为该类型。此前,只要遇到一个此类属性就会中止整次转储,不产生任何文件。
要针对某个游戏版本验证生成的 SDK,请包含 UE4SS_SDK/LayoutAsserts.hpp。它为每个生成类型的大小、对齐及每个成员偏移提供 static_assert。默认不会包含该文件,因此布局问题会精确表现为相应类型的断言失败,而不会破坏整个 SDK 的构建。UE4SS_SDK/RuntimeSDKTest.hpp 则会在运行时对照正在运行的游戏执行等效检查。
UE4SS 后端已编译进 UE4SS,所以即使不存在任何配置文件,生成器也能工作。把后端描述文件放入 <working_dir>/UE4SS_SDK_Backends 可添加后端;若文件名与内置后端相同(UE4SS.json),则会覆盖内置后端。随项目提供的 assets/UE4SS_SDK_Backends/UE4SS.json 正是生成内置后端所用的文件,因此也可作为自定义的起点。
工作原理
生成器生成类、结构体和枚举,设计目标是在以 UE4SS 为 UE 后端的 C++ Mod 中轻松使用。
如果不想以 UE4SS 为后端,就需要自行提供所有必需的 UE 类型,例如 UObject,以及 TArray、TObjectPtr 和 TWeakObjectPtr 等模板类型。
还必须提供 UE 的 FindObject<T> 函数模板,因为运行时通过它查找函数。后端必须支持以下调用:FindObject<UFunction>(nullptr, L"/Script/Engine.CharacterMovementComponent:SetMovementMode")。
使用方法
以下指南面向 UE4SS C++ Mod,但也可以调整为适用于任意 UE 后端。关于使用其他后端的更多信息,请查看 UE4SS-settings.ini 的 [SDKGenerator] 节。
- 确保
GuiConsoleEnabled和GuiConsoleVisible均设为 1,然后启动游戏。 - 在 GUI 中进入
Dumpers页签,点击Generate SDK。此时<Game>/Binaries/Win64中应出现UE4SS_SDK目录。 - 将整个目录复制到 C++ Mod 目录中。
- 在 C++ Mod 的
CMakeLists.txt中添加add_subdirectory(UE4SS_SDK),并确保把UE4SS_SDK加入target_link_libraries。
在 C++ 中使用
要在代码中使用 SDK,必须包含你要使用的相应部分。
下面的示例原则上适用于任意后端。使用 UE4SS 后端和其他后端的唯一区别,是基础 UE 类型的来源。
如果以 UE4SS 为后端,下面直接针对 AActor 的示例不适用,因为 UE4SS 已提供该类型;但将其用于 UE4SS 尚未提供的任何类型时,示例仍然适用:
#include <UE4SS_SDK/Script/Engine/Actor.hpp>
// This example is abbreviated, and doesn't include 'int main()'
// or any other unrelated but required code.
void DoStuff()
{
// For this example, assume 'Actor' is a valid AActor.
AActor* Actor{};
// The 'GetChildren' function returns 'TArray<AActor*>', so you must have provided 'TArray<T>'.
auto& Array = AsActor->Children;
for (const auto& Element : Array)
{
printf("Element: %S", Element->GetFullName().c_str());
}
}
示例中的英文注释译文:此例经过简化,未包含 int main() 或其他无关但必需的代码;假设 Actor 是有效的 AActor。GetChildren 函数返回 TArray<AActor*>,因此需要自行提供 TArray<T>。
译注:以上代码保留原文。原文声明变量
Actor,后面却使用AsActor,且注释提到的GetChildren与实际Children访问不一致;实际使用时需结合自己的代码修正这些标识。
原文:docs/feature-overview/sdk-generator.md · 固定提交 560411f18512 · 来源与 MIT 许可