Skip to main content

Quick start

This tutorial follows the official zlua-demo sample and walks through C# calling Lua and Lua accessing C#. Clone the Demo project and follow along.

Mono · DoneIl2Cpp · Done — Examples on this page work in both Editor and Player; Player builds require Generate. See Compatibility.

:::tip Sample sources

PieceLink
C# entryAssets/Bootstrap.cs
C# typesAssets/Demo.cs
Lua moduleLuaScripts/app.lua

:::

Prerequisites

  • Finish Installation (Settings + Install), or clone zlua-demo
  • Any Unity version listed in Compatibility; Play in the Editor is enough to start

Step 1: Initialize ZLua

Bootstrap registers the Lua loader and initializes the domain before the scene loads:

[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void InitZLuaOnStartup()
{
LuaAppDomain.Initialize(LoadLuaModule);
}

LoadLuaModule("app") reads LuaScripts/app.lua in the Editor (see Bootstrap.cs).

You do not manually create a LuaState, require, or register wraps — ZLua wires the CLR and Lua environment at startup.

Step 2: C# calling Lua

Use LuaAppDomain.GetFunction<T> to obtain a Delegate for a Lua function; the Lua module return table exports named functions.

Action AppMain;
Func<int, int, int> AppAdd;

void Awake()
{
// After InitZLuaOnStartup (Initialize); do not use static field initializers
AppMain = LuaAppDomain.GetFunction<Action>("app", "main");
AppAdd = LuaAppDomain.GetFunction<Func<int, int, int>>("app", "add");
}

void Start()
{
AppMain();
int value = AppAdd(10, 20);
Debug.Log($"AppAdd(10,20)={value}"); // 30
}

Full logic: LuaScripts/app.lua.

Expected Console output (Editor Play)

lua main start
[test_call_static_method] start
Demo.Add: 8
...
AppAdd(10,20)=30

Step 3: Lua accessing C# types

Assembly alias

Load assemblies and types lazily via the CSharp root table:

CSharp['AC'] = CSharp['Assembly-CSharp'] -- short alias used by the Demo

Static methods

print(CSharp.AC.Demo.Add(3, 5)) -- 8
print(CSharp.AC.Demo.Multi(3, 5)) -- 15

Construction and instance methods

local demo = CSharp.AC.Demo()
print(demo:GetX()) -- 0
demo:SetX(10)

Fields and properties

Fields and parameterless properties share the same access style:

demo.x = 20
print(demo:GetX()) -- 20

Static members

CSharp.AC.Demo.s_x = 10
print(CSharp.AC.Demo.GetSX()) -- 10

These appear in the test_* helpers in app.lua.

Access cheat sheet

ActionLua
ConstructCSharp.AC.Demo()
Instance field/propertydemo.x / demo:SetX(10)
Instance methoddemo:Run(10)
Static fieldCSharp.AC.Demo.s_x
Static methodCSharp.AC.Demo.Add(3, 5)
Namespaced typeCSharp.AC['MyGame.UI.Panel']

Step 4 (optional): Method overloads

Demo.Run has int and string overloads. Use a full-signature key, or register a short name for colon calls:

demo['Run(System.Int32)'](demo, 10)

local run_i32 = demo['Run(System.Int32)']
zlua.register_method("run_i32", run_i32)
demo:run_i32(10)

See Method overloads.

Building an Il2Cpp Player

  1. Run ZLua/Generate/All (emit C++ stubs)
  2. Configure SyncLuaScriptsToStreamingAssets
  3. Build Settings → Il2Cpp → Build

See Project status and Editor vs Player.

Mono / Il2Cpp support

This pageMono (Editor)Il2Cpp (Player)
Initialize + GetFunction
Static/instance methods, fields
Property / overloads✅ (semantics follow the Spec)

Common errors

ErrorCheck
module 'app' not foundLuaScripts/app.lua exists; LoadLuaModule path
Type Demo is nilWrong assembly name; use CSharp.AC.Demo
AppAdd returns 0Module did not return { add = add }; or method name ≠ GetFunction argument
No Lua output in PlayerMissing StreamingAssets/LuaScripts/app.lua.txt sync

Next steps

Follow the Guides path:

  1. Install & Lua version
  2. Init & minimal interop
  3. Build pipeline
  4. Lua calling C#C# calling Lua → …

Learning path

PreviousInstallation
NextInstall & Lua version