[翻译]Integrating Lua
一篇名为Integrating Lua的Wiki页面翻译。
原文链接:https://wiki.unrealengine.com/Integrating_Lua
Integrating Lua
Overview
欢迎来到我的第三个Wiki页面,这个页面是关于那个很棒的游戏引擎的——虚幻引擎!这篇文章包含了人们最近问我数次的那个问题,我认为这将对游戏逻辑编程和一个高水平的mod-abilty(模块化能力?):整合Lua很有用。
Requirements
Starting off : code in our project
Aquiring:
现在,我们需要向项目中引入Lua,以便于其与我们的项目一起编译并包含在最终游戏中。但是首先,我们需要获取到Lua的二进制文件。有些项目会为您提供预编译的二进制文件,或者您也可以自行编译!因为编译的过程耗费时间,而且这个过程是必要的,所以我们将使用预编译的版本。LuaBinaries是一个很棒的项目,它始终是最新的,并且具有适用于每个平台的二进制文件(在本文中,我们将只涉及Windows)。选择最新版本,然后选择Windows库,接着选择静态(Static),因为我们会将Lua嵌入到游戏的可执行文件中,然后根据需要搜索软件包。在我们下载过这些包后,我们应该在它们的结构中找到如下文件:
- Include/(essential includes for working with Lua)
- luaxlib.h
- lua.h
- lua.hpp
- luaconf.h
- lualib.h
- luaXX.lib(XX代表Lua的当前版本,例如Lua 5.3.3就为lu a53.lib)
现在,我们拥有了二进制文件和包含文件,我们可以开始我们的集成工作了!
Copying the files
在虚幻引擎中链接Lua很容易。首先,我们需要在项目目录中创建一个新文件夹,将Lua内容放入其中。我个人更喜欢在项目的主目录(.uproject所在的位置)中创建一个新文件夹,并将其命名为“ThirdParty”。然后在这个文件夹中,我创建了一个名为“Lua”的文件夹,并将其分为“includes”和“libraries”。结构如下:
- Project Home/
- ThirdParty/
- Lua/
- includes/(我们只需要复制一次,因为它们与体系结构没有区别,最后请注意“s”)
- libraries/
- luaXX.x64.lib(这是您在Win64包中下载的库文件,重命名来做区分)
- luaXX.x32.lib(这是您在Win32包中下载的库文件,重命名来做区分)
- Lua/
- ThirdParty/
Linking
在Visual Studio中,打开YourProjectName.Build.cs,这个文件位于 Source/YourProjectName/ 文件夹中。默认情况下,此文件仅链接默认引擎模块。要对此链接Lua,我们需要向其中添加一些代码。由于展示每一个细节实在是太多了,所以我只向你展示我对Build.cs文件的改动:
1 | using System.IO; |
“LoadLua”方法检查我们是否在Windows上,如果是,则根据编译的体系结构创建一个包含“x64”或“x86”的字符串,因此我们可以轻松的找到lib文件。然后,我们创建库路径,该路径就是(在这个例子中为“ThirdParty/”)/Lua/libraries。从那里,我们将平台字符串附加到文件名的前缀和后缀,因此最后应该是lua53.xxx.lib。此路径已添加到PublicAdditionalLibraries中,这会强制编译器使用我们放在其中的lib文件。我们还将includes目录添加到PublicIncludePaths,以便编译器找到我们的includes。最后也很重要的一点是,我们向已编译的游戏中添加了一个定义:WITH_LUA_BINDING = x,其中x为0(不支持Lua)或1(支持Lua)。
First steps
现在,我们已经将Lua二进制文件集成到我们的游戏中,让我们通过在Visual Studio中右键单击该项目并选择“Build”来进行尝试。它应该会成功!下一步:编写一个蓝图节点,该节点从我们输入的字符串中执行Lua代码。打开您创建的蓝图函数库的头文件(.h)。空文件如下所示:
1 |
|
首先,在顶部添加Lua包含项,以便编译器知道声明函数的位置。为此,请在其他包含项的头部添加#include "lua.hpp"
。接下来,我们向其中添加一个新的UFUNCTION,将其解析为带有以下声明的蓝图节点:
1 | public: |
这将创建一个可调用的蓝图节点,该节点带有一个字符串(FString),我们可以在其中输入将要运行的Lua代码。请注意,这是静态的,因为我们没有要在上下文中调用此对象的对象,换言之,我们想在没有任何目标的情况下从任何地方调用它。让我们进入LuaBlueprints.cpp文件,该文件应该为空(include文件除外)。我们为RunLua函数添加定义:
1 | void ULuaBlueprints::RunLua(const FString& code) |
这很容易。它使用Lua C API创建一个新的Lua状态,将其分配给名为L的变量。然后,打开标准的lua库(例如math),然后通过执行luaL_dostring()运行代码。这将Lua状态L作为一个参数,并将要运行的代码作为另一个参数。该函数返回一个整数,如果一切正常,则返回0。如果不为0,则显然出了问题。在这种情况下,我使用UE_LOG将其打印到日志中。注意,我们通过lua_tostring(L,-1)得到Lua错误消息。