创建 Lua Mod
开始之前
要在 UE4SS 中创建 Lua Mod,应先:
- 了解如何在目标游戏中安装 UE4SS,并确认其运行正常。
- 能编写基础 Lua 代码(参阅官方书籍 Programming in Lua 及其后续版本,或其他推荐的在线教程)。
- 理解 Unreal Engine 的对象模型以及游戏 Mod 制作的基础知识。
最简 Lua Mod 的结构
UE4SS 中的 Lua Mod 是一组 Lua 脚本,放置在 UE4SS 安装目录的 Mods/ 内的某个文件夹中。本例将其命名为 MyLuaMod。
要使其被加载并执行:
- Mod 文件夹必须包含
scripts子文件夹,并在其中放置main.lua,结构如下:
Mods\
...
MyLuaMod\
scripts\
main.lua
...
Mods\MyLuaMod\scripts\main.lua文件中需要有 Lua 代码,例如:
print("[MyLuaMod] Mod loaded\n")
- 必须在
Mods\mods.txt中新增一行,写入 Mod 文件夹名称(即 Mod 名称),并用1启用、0禁用:
...
MyLuaMod : 1
...
自定义功能写在 main.lua 中。需要时可以从该文件加载其他 Lua 文件,包括自行创建 Lua 模块或导入各种库。
Lua Mod 能做什么
UE4SS 提供给 Lua 使用的 API 记录在“Lua API”章节的各个子章节中。借助这些函数和类,可以查找并操作内存中的 Unreal Engine 对象实例、创建新对象、修改现有对象、调用方法和访问字段。
本质上,你做的事情与 Unreal Engine 游戏开发者在代码中做的完全相同;区别在于你需要使用 UE4SS 定位所需对象,并做一些推断,而开发者已掌握这些对象的位置和含义,因为他们拥有源码。
创建简单数据类型
如果需要创建类似结构体的类对象(例如 FVector)并传给 Unreal Engine 函数,UE4SS 允许改用包含该类字段的 Lua 表,例如 {X=1.0, Y=2.0, Z=3.0}。
使用 Lua C 库
如果需要加载带有原生代码的 Lua C 库(例如 Windows 下含有 DLL 的库),可以直接把这些 DLL 放入同一个 \scripts\ 文件夹中。
配置 Lua Mod 开发环境
将代码编辑器或 IDE 正确配置为支持 Lua 开发,并使其了解 UE4SS API 后,编写 Mod 会容易得多。
- 配置编辑器/IDE,使其支持 Lua 语法高亮和代码补全。如果使用 VSCode,请参阅使用自定义 Lua 绑定。
- 确保你的 UE4SS 构建包含
Mods\shared\Types.lua(GitHub Releases 中的开发版包含此文件)。这样 IDE 就能加载 UE4SS API 定义。 - (可选)从 UE4SS GUI 控制台转储 Lua 绑定,并按照建议加载它们。
随后在 IDE 中打开 UE4SS 安装目录下的 Mods/ 文件夹,并在其中创建或修改 Mod。
应用代码变更
开发 Lua Mod 的主要优势是可以快速编辑 Lua 源码,无需像 C++ Mod 那样每次重新编译/构建 C++ Mod 库,还能在不重启游戏的情况下重试。
可以选择:
- 在 UE4SS GUI 控制台的
Console页签点击Restart All Mods,重新加载所有 Mod。 - 在
UE4SS-settings.ini中启用Hot reload,再使用指定快捷键(默认Ctrl+R)执行同一操作。
第一个 Mod
在 Mod 的 main.lua 文件中编写代码,尝试访问目标游戏中的 Unreal Engine 对象,并执行一些能在 UE4SS 控制台观察到的操作。
可以先试试:
print("[MyLuaMod] Mod loaded\n")
确认代码正常运行后,即可开始实现实际功能。
下面的示例比较通用,应该适用于 UE4SS 支持的许多游戏。
它注册 Ctrl+F1 快捷键;按下时读取玩家坐标,并计算玩家自上次按下快捷键以来移动的距离。
注意,日志中的
玩家坐标的获取过程如下:
- 使用 UE4SS 的
UEHelpers类获取玩家控制器。 - 获取
Pawn,它表示 Unreal Engine 中玩家可控制的实际“物理”实体。 - 调用 Unreal Engine 的
K2_GetActorLocation方法,通过Pawn的父类Actor获取其位置。 - 返回的位置是 Unreal Engine 类型
FVector的三维向量,包含X、Y、Z字段。
local UEHelpers = require("UEHelpers")
print("[MyLuaMod] Mod loaded\n")
local lastLocation = nil
function ReadPlayerLocation()
local FirstPlayerController = UEHelpers:GetPlayerController()
local Pawn = FirstPlayerController.Pawn
local Location = Pawn:K2_GetActorLocation()
print(string.format("[MyLuaMod] Player location: {X=%.3f, Y=%.3f, Z=%.3f}\n", Location.X, Location.Y, Location.Z))
if lastLocation then
print(string.format("[MyLuaMod] Player moved: {delta_X=%.3f, delta_Y=%.3f, delta_Z=%.3f}\n",
Location.X - lastLocation.X,
Location.Y - lastLocation.Y,
Location.Z - lastLocation.Z)
)
end
lastLocation = Location
end
RegisterKeyBind(Key.F1, { ModifierKey.CONTROL }, function()
print("[MyLuaMod] Key pressed\n")
ExecuteInGameThread(function()
ReadPlayerLocation()
end)
end)
当游戏加载到可以移动角色的阶段后,按一次快捷键,移动玩家,再按一次。Mod 会生成如下或非常相近的输出:
...
[2024-01-09 19:37:27] Starting Lua mod 'MyLuaMod'
[2024-01-09 19:37:27] [Lua] [MyLuaMod] Mod loaded
...
[2024-01-09 19:37:32] [Lua] [MyLuaMod] Key pressed
[2024-01-09 19:37:32] [Lua] [MyLuaMod] Player location: {X=-63.133, Y=4.372, Z=90.000}
[2024-01-09 19:37:39] [Lua] [MyLuaMod] Key pressed
[2024-01-09 19:37:39] [Lua] [MyLuaMod] Player location: {X=788.232, Y=-639.627, Z=90.000}
[2024-01-09 19:37:39] [Lua] [MyLuaMod] Player moved: {delta_X=851.364, delta_Y=-643.999, delta_Z=0.000}
...
原文:docs/guides/creating-a-lua-mod.md · 固定提交 560411f18512 · 来源与 MIT 许可