Setting Up UnLua in UE 5.8: From Plugin Compilation to the Lua Startup Script

Jul 5, 2026

1632 words

8 min read

Game Development Learning

I recently integrated UnLua into a UE 5.8 project. The main problem was not “how to use UnLua”, but that older UnLua source code runs into a set of compile-time compatibility issues under UE 5.8. This article organizes the full setup process: why UnLua is useful, what changed in UE 5.8, and a practical configuration flow that can actually be applied.

This article is based on a UE 5.8 compatibility pass for Tencent UnLua. It is not an official release. It is only a record of one UE 5.8 integration practice.

Original project: https://github.com/Tencent/UnLua

Why Use UnLua in a UE Project

UnLua connects Lua scripts to Unreal Engine, so part of the gameplay logic can be moved out of C++ or Blueprints and organized as scripts.

The most direct benefit is faster iteration. C is well suited for low-level systems, performance-sensitive logic, and stable frameworks. But if every gameplay flow, UI behavior, quest script, and trigger rule is written in C, every small change has to go through compilation, hot reload, or even an editor restart. That slows down the workflow. Lua files are plain text, so they are cheap to edit and organize, which makes them suitable for frequently changing business logic.

Another important value of UnLua is that it can connect to UE’s object system. Lua code can access reflected objects such as UObject, UClass, UFunction, and UProperty, and can also bind to Blueprint classes. This allows a project to keep a relatively clear division of responsibility:

  • C++ handles core systems, performance-sensitive code, low-level frameworks, and complex engine extensions.
  • Blueprints handle asset organization, visual setup, animation/UI binding, and designer-editable content.
  • Lua handles gameplay flow, UI interactions, level scripts, quest logic, event logic, and rapid prototypes.

If the project may need hot updates in the future, Lua is also a more natural fit. Hot updates still require a complete system for asset management, version control, download validation, and so on, but script-layer logic is more suitable for runtime loading and replacement than C++ modules.

There is also a more practical point: Lua files are text, which makes them friendly to agent-based or AI-assisted development. Compared with directly modifying Blueprint assets, generating, reviewing, and rolling back Lua logic is much lighter.

Why UE 5.8 Needs Extra Adaptation

The official UnLua version is not directly prepared for UE 5.8. UE 5.8 changes parts of the build toolchain and engine APIs. If old plugin source code is dropped directly into a project, a common result is seeing this prompt when opening the project:

Missing Modules: UnLua, UnLuaEditor

This prompt does not mean the project is broken. It means .uproject has enabled UnLua, but UE cannot find plugin DLLs that are usable with the current engine version. The usual cause is that the plugin has not been compiled yet, or it was compiled for another UE version.

During this UE 5.8 adaptation, the main changes were:

  1. UE 5.8 uses a newer build toolchain

    In local verification, UE 5.8 used its bundled .NET 10 SDK, the VS2022 MSVC toolchain, and Windows SDK. Some older UnLua UBT/UHT helper projects were still written for an older framework, so they ran into incompatibilities around net6.0, old enum values, and old APIs.

  2. The UHT plugin API changed

    UnLua’s default parameter collector depends on the UHT export flow. In UE 5.8, modules and packages need to be traversed through Session.Modules. The old approach does not compile directly.

  3. More UObject field links use TObjectPtr

    In UE 5.8, fields such as UStruct::Children and UField::Next are already TObjectPtr<UField>. Old code that manipulates those linked lists as UField** will hit type mismatches.

  4. The Delegate API changed

    Multicast delegate calls need to adapt to the newer ProcessDelegate<UObject>(Params) form.

  5. The metadata API changed

    UMetaData::CopyMetadata needs to become FMetaData::CopyMetadata, with the corresponding include added.

  6. Format string checks are stricter

    FString::Printf now favors format strings that can be checked at compile time. Old code that passes a variable as the format string can fail under UE 5.8.

  7. Lua internal type names conflict with UE type names

    Lua’s internal TString can conflict with UE 5.8 types or aliases. When including Lua internal headers, the name needs to be isolated.

So the key to setting up UnLua in UE 5.8 is not simply “copy the plugin into the project”. The first requirement is making sure the UnLua source code can be fully compiled by the UE 5.8 toolchain.

Preparation

You need:

  • Unreal Engine 5.8
  • Visual Studio 2022 C++ toolchain
  • Windows SDK
  • A UE 5.8 C++ project
  • UnLua plugin source code adapted for UE 5.8

If the project is Blueprint-only, it is recommended to add an empty C class in UE first, so the project generates C project structure such as Source, .Target.cs, and .Build.cs. UnLua is a C++ plugin, and it eventually needs to be compiled through Unreal Build Tool.

Final Directory Structure

After configuration, the project structure should roughly look like this:

YourProject/
  Config/
    DefaultUnLuaEditor.ini
  Content/
    Script/
      Main.lua
  Plugins/
    UnLua/
      UnLua.uplugin
      Source/
      Content/
      Config/
  Source/
  YourProject.uproject

In this structure:

  • Plugins/UnLua is the plugin itself.
  • Config/DefaultUnLuaEditor.ini configures UnLua editor behavior and the startup module.
  • Content/Script/Main.lua is the default Lua startup entry.

Step 1: Copy the UnLua Plugin

Copy the UE 5.8-adapted UnLua plugin into the project:

YourProject/Plugins/UnLua

If the project already has an old Plugins/UnLua directory, back it up first, then place the new plugin there.

Do not treat Binaries or Intermediate generated by an old version as reliable artifacts. UE plugins are best recompiled on the current machine and current engine version.

Step 2: Enable the Plugin in uproject

Open the project’s .uproject file and add UnLua to the Plugins array:

{
  "Name": "UnLua",
  "Enabled": true
}

A simplified example:

{
  "FileVersion": 3,
  "EngineAssociation": "5.8",
  "Modules": [
    {
      "Name": "YourProject",
      "Type": "Runtime",
      "LoadingPhase": "Default"
    }
  ],
  "Plugins": [
    {
      "Name": "UnLua",
      "Enabled": true
    }
  ]
}

If the project already has other plugins, do not overwrite the original Plugins array. Just append the UnLua entry.

Step 3: Add the UnLua Configuration

Create or modify:

Config/DefaultUnLuaEditor.ini

Write:

[/Script/UnLuaEditor.UnLuaEditorSettings]
bAutoStartup=True
bEnableDebug=True
HotReloadMode=Manual
LuaVersion=lua-5.4.3

[/Script/UnLua.UnLuaSettings]
StartupModuleName=Main

The key setting here is:

StartupModuleName=Main

It means UnLua will load Content/Script/Main.lua when it starts.

Step 4: Add the Lua Startup File

Create this directory:

Content/Script

Then create:

Content/Script/Main.lua

Write a minimal startup module:

local M = {}

function M.Initialize()
    print("UnLua initialized")
end

return M

This file is only used to verify the UnLua startup path. Once the project starts implementing real logic, you can split modules here, initialize systems, and load other Lua files.

Step 5: Generate Project Files

Open PowerShell and run:

& "C:\Program Files\Epic Games\UE_5.8\Engine\Build\BatchFiles\Build.bat" -projectfiles -project="C:\YourProject\YourProject.uproject" -game -rocket -progress

Replace C:\YourProject\YourProject.uproject with your own project path.

This step lets UE recognize the plugin, modules, and project structure again.

Step 6: Compile the Editor Target

Run:

& "C:\Program Files\Epic Games\UE_5.8\Engine\Build\BatchFiles\Build.bat" YourProjectEditor Win64 Development -Project="C:\YourProject\YourProject.uproject" -WaitMutex -FromMsBuild -NoHotReloadFromIDE

You need to replace two parts:

  • YourProjectEditor: the project name plus Editor
  • C:\YourProject\YourProject.uproject: the full path to the project’s .uproject

It is recommended to keep:

-NoHotReloadFromIDE

This can avoid compile failures caused by Live Coding or Hot Reload locking modules. When configuring plugins, it is best to close UE Editor and the Live Coding Console before running a full compilation.

After compilation succeeds, the project should generate:

Plugins/UnLua/Binaries/Win64/UnrealEditor-UnLua.dll
Plugins/UnLua/Binaries/Win64/UnrealEditor-UnLuaEditor.dll

After these two DLLs exist, opening .uproject usually should no longer show:

Missing Modules: UnLua, UnLuaEditor

UE 5.8 Compatibility Change Summary

If you are adapting the official UnLua source code to UE 5.8 by yourself, these are the actual areas changed during this pass.

Lua.Build.cs

Location:

Source/ThirdParty/Lua/Lua.Build.cs

The old code used enum checks such as WindowsCompiler.VisualStudio2019. This enum no longer applies in UE 5.8. It can be changed to a string check:

Target.WindowsPlatform.Compiler.ToString() == "VisualStudio2019"

Change the UHT Helper Project to net10.0

Location:

Source/UnLuaDefaultParamCollectorUbtPlugin/UnLuaDefaultParamCollectorUbtPlugin.ubtplugin.csproj

Change:

<TargetFramework>net6.0</TargetFramework>

to:

<TargetFramework>net10.0</TargetFramework>

Also remove the unnecessary Microsoft.CSharp package reference so it matches UE 5.8’s bundled .NET 10.

Adapt the UHT Session API

Location:

Source/UnLuaDefaultParamCollectorUbtPlugin/UnLuaDefaultParamCollectorUbtPlugin.cs

In UE 5.8, modules need to be traversed from:

Session.Modules

Then packages are traversed from each module. The old UHT export approach cannot be used directly.

Fix the MetaClass Syntax

Location:

Source/UnLua/Public/UnLuaSettings.h

Change:

MetaClass="Object"

to:

MetaClass="/Script/CoreUObject.Object"

Add Legacy Template Compatibility Definitions

Location:

Source/UnLua/Public/UnLuaTemplate.h

Add compatibility definitions for:

TChooseClass
TIsTriviallyDestructible
TIsTriviallyCopyConstructible

These are template types used by older UnLua code that need compatibility definitions under UE 5.8.

Avoid Lua Internal TString Conflicts

Locations:

Source/UnLua/Private/LuaCore.cpp
Source/UnLua/Private/LuaEnv.cpp

When including Lua internal headers, isolate the name like this:

#define TString LuaTString
// include Lua internal headers
#undef TString

Adjust AsyncObjectFlags

Location:

Source/UnLua/Private/LuaEnv.cpp

Remove the incompatible:

AsyncLoading

Keep:

Async

Metadata Copy API

Location:

Source/UnLua/Private/LuaFunction.cpp

Add:

#include "UObject/MetaData.h"

Then change:

UMetaData::CopyMetadata(...)

to:

FMetaData::CopyMetadata(...)

Delegate Call Form

Location:

Source/UnLua/Private/ReflectionUtils/FunctionDesc.cpp

Change multicast delegate invocation to:

ScriptDelegate->ProcessDelegate<UObject>(Params);

Use Literal Format Strings with FString::Printf

Location:

Source/UnLua/Private/UnLuaConsoleCommands.cpp

Do not pass a variable as the format argument to FString::Printf. Use a literal such as TEXT(R"(... )") directly instead.

Fix a Missing Logging Argument

Location:

Source/UnLua/Private/UnLuaBase.cpp

One log format string requires two %s arguments but only passes one argument. Add:

ANSI_TO_TCHAR(__FUNCTION__)

Adapt TObjectPtr Field Linked Lists

Location:

Source/UnLua/Private/LuaOverridesClass.cpp

In UE 5.8:

UStruct::Children
UField::Next

are TObjectPtr<UField>, so linked-list operations need to use:

TObjectPtr<UField>*

instead of the old UField**.

Common Issues

The Project Still Shows Missing Modules When Opened

This means UE still cannot find plugin modules that are usable with the current engine version. Check:

  • Whether Plugins/UnLua exists.
  • Whether .uproject enables UnLua.
  • Whether YourProjectEditor has been compiled successfully.
  • Whether UnrealEditor-UnLua.dll and UnrealEditor-UnLuaEditor.dll have been generated.
  • Whether UE Editor or Live Coding Console is still open.

It is recommended to close the editor and Live Coding Console, then compile again.

Compilation Says Live Coding Is Running

Add this to the build command:

-NoHotReloadFromIDE

If it still fails, fully close UE Editor and the Live Coding Console, then run Build.bat again.

What If the Project Is Blueprint-Only

Add an empty C class in the UE editor first, generate the C project structure, and then configure UnLua. Otherwise, many C++ plugin-related build steps will be incomplete.

Should Binaries Be Committed

In general, it is not recommended to commit:

Plugins/UnLua/Binaries/
Plugins/UnLua/Intermediate/

They are build artifacts generated for the current machine and current engine version. It is better to commit source code and configuration, then let each machine compile its own binaries.

Recommended .gitignore:

Binaries/
Intermediate/
Saved/
DerivedDataCache/

*.pdb
*.dll
*.modules
*.target

Summary

When setting up UnLua in UE 5.8, three things matter most.

First, use UnLua source code that has already been adapted for UE 5.8. If old source code is copied directly into a project, it is likely to fail around UBT/UHT, Delegate APIs, TObjectPtr, metadata APIs, and similar areas.

Second, connect the plugin to the project: copy it to Plugins/UnLua, enable it in .uproject, add DefaultUnLuaEditor.ini, and create Content/Script/Main.lua.

Third, use UE 5.8’s Build.bat to compile YourProjectEditor Win64 Development, so the current engine version generates its own UnLua and UnLuaEditor DLLs.

Once the plugin modules compile successfully, prompts such as Missing Modules: UnLua, UnLuaEditor should disappear. After that, gameplay, UI, or level logic can gradually be moved into Lua.

Setting Up UnLua in UE 5.8: From Plugin Compilation to the Lua Startup Script
Published on
Jul 5, 2026

Enter keywords to start searching