创建 Lua Mod

创建 Lua Mod

开始之前

要在 UE4SS 中创建 Lua Mod,应先:

  • 了解如何在目标游戏中安装 UE4SS,并确认其运行正常。
  • 能编写基础 Lua 代码(参阅官方书籍 Programming in Lua 及其后续版本,或其他推荐的在线教程)。
  • 理解 Unreal Engine 的对象模型以及游戏 Mod 制作的基础知识。

最简 Lua Mod 的结构

UE4SS 中的 Lua Mod 是一组 Lua 脚本,放置在 UE4SS 安装目录的 Mods/ 内的某个文件夹中。本例将其命名为 MyLuaMod。

要使其被加载并执行:

  1. Mod 文件夹必须包含 scripts 子文件夹,并在其中放置 main.lua,结构如下:
Mods\
    ...
    MyLuaMod\
        scripts\
            main.lua
    ...
  1. Mods\MyLuaMod\scripts\main.lua 文件中需要有 Lua 代码,例如:
print("[MyLuaMod] Mod loaded\n")
  1. 必须在 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 会容易得多。

  1. 配置编辑器/IDE,使其支持 Lua 语法高亮和代码补全。如果使用 VSCode,请参阅使用自定义 Lua 绑定。
  2. 确保你的 UE4SS 构建包含 Mods\shared\Types.lua(GitHub Releases 中的开发版包含此文件)。这样 IDE 就能加载 UE4SS API 定义。
  3. (可选)从 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 快捷键;按下时读取玩家坐标,并计算玩家自上次按下快捷键以来移动的距离。

注意,日志中的 print 调用在方括号中包含 Mod 名称,便于在控制台的其他日志中找到该 Mod 的输出。

玩家坐标的获取过程如下:

  1. 使用 UE4SS 的 UEHelpers 类获取玩家控制器。
  2. 获取 Pawn,它表示 Unreal Engine 中玩家可控制的实际“物理”实体。
  3. 调用 Unreal Engine 的 K2_GetActorLocation 方法,通过 Pawn 的父类 Actor 获取其位置。
  4. 返回的位置是 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 许可