Baike.dev
All toolsAI codingTrendingOpen sourceNewsSubmit
Log in
< Back to tools
L

Lua-CSharp

> 编程语言
Open source

High performance Lua interpreter implemented in C# for .NET and Unity

839 stars0 likes0 views
WebsiteGitHub

About

High performance Lua interpreter implemented in C# for .NET and Unity

Lua-CSharp

High performance Lua interpreter implemented in C# for .NET and Unity

English | 日本語

Overview

Lua-CSharp is a library that provides a Lua interpreter implemented in C#. By integrating Lua-CSharp, you can easily embed Lua scripts into your .NET applications.

Lua-CSharp leverages the latest C# features, designed with low allocation and high performance in mind. It is optimized to deliver maximum performance when used for interoperation between C# and Lua in C# applications. Below is a benchmark comparison with MoonSharp and NLua:

MoonSharp generally provides good speed but incurs significant allocations due to its design. NLua, being a C-binding implementation, is fast, but introduces substantial overhead when interacting with the C# layer. Lua-CSharp, fully implemented in C#, allows for seamless interaction with C# code without additional overhead. Moreover, it operates reliably in AOT environments since it does not rely on IL generation.

Features

  • Lua 5.2 interpreter implemented in C#
  • Easy-to-use API integrated with async/await
  • Support for exception handling with try-catch
  • High-performance implementation utilizing modern C#
  • Unity support (works with both Mono and IL2CPP)

Installation

NuGet packages

To use Lua-CSharp, .NET Standard 2.1 or higher is required. The package can be obtained from NuGet.

.NET CLI

dotnet add package LuaCSharp

Package Manager

Install-Package LuaCSharp

Unity

You can also use Lua-CSharp with Unity. For details, see the Lua.Unity section.

Quick Start

By using the LuaState class, you can execute Lua scripts from C#. Below is a sample code that evaluates a simple calculation written in Lua.

using Lua;

// Create a LuaState
var state = LuaState.Create();

// Execute a Lua script string with DoStringAsync
var results = await state.DoStringAsync("return 1 + 1");

// 2
Console.WriteLine(results[0]);

[!WARNING] LuaState is not thread-safe. Do not access it from multiple threads simultaneously.

LuaValue

Values in Lua scripts are represented by the LuaValue type. The value of a LuaValue can be read using TryRead(out T value) or Read().

var results = await state.DoStringAsync("return 1 + 1");

// double
var value = results[0].Read();

You can also get the type of the value from the Type property.

var isNil = results[0].Type == LuaValueType.Nil;

Below is a table showing the type mapping between Lua and C#.

Lua C#
nil LuaValue.Nil
boolean bool
string string
number double, float, int
table LuaTable
function LuaFunction
(light)userdata object
userdata ILuaUserData
thread LuaState

When creating a LuaValue from the C# side, compatible types are implicitly converted into LuaValue.

LuaValue value;
value = 1.2;           // double   ->  LuaValue
value = "foo";         // string   ->  LuaValue
value = new LuaTable() // LuaTable ->  LuaValue

LuaTable

Lua tables are represented by the LuaTable type. They can be used similarly to LuaValue[] or Dictionary.

// Create a table in Lua
var results = await state.DoStringAsync("return { a = 1, b = 2, c = 3 }");
var table1 = results[0].Read();

// 1
Console.WriteLine(table1["a"]);

// Create a table in C#
results = await state.DoStringAsync("return { 1, 2, 3 }");
var table2 = results[0].Read();

// 1 (Note: Lua arrays are 1-indexed)
Console.WriteLine(table2[1]);

Global Environment

You can access Lua's global environment through state.Environment. This table allows for easy value exchange between Lua and C#.

// Set a = 10
state.Environment["a"] = 10;

var results = await state.DoStringAsync("return a");

// 10
Console.WriteLine(results[0]);

Standard Libraries

You can use Lua's standard libraries as well. By calling state.OpenStandardLibraries(), the standard library tables are added to the LuaState.

using Lua;
using Lua.Standard;

var state = LuaState.Create();

// Add standard libraries
state.OpenStandardLibraries();

var results = await state.DoStringAsync("return math.pi");
Console.WriteLine(results[0]); // 3.141592653589793

For more details on standard libraries, refer to the Lua official manual.

[!WARNING] Lua-CSharp does not support all functions of the standard libraries. For details, refer to the Compatibility section.

Functions

Lua functions are represented by the LuaFunction type. With LuaFunction, you can call Lua functions from C#, or define functions in C# that can be called from Lua.

Calling Lua Functions from C#

-- lua2cs.lua

local function add(a, b)
    return a + b
end

return add;
var state = LuaState.Create();
var results = await state.DoFileAsync("lua2cs.lua");
var func = results[0];

// Execute the function or any callable with arguments
var funcResults = await state.CallAsync(func, [1, 2]);

// 3
Console.WriteLine(funcResults[0]);

To avoid array allocation, an API is also provided that passes arguments using the stack.

…
-- cs2lua.lua

return add(1, 2)

[!TIP]
Defining functions with LuaFunction can be somewhat verbose. When adding multiple functions, it is recommended to use the Source Generator with the [LuaObject] attribute. For more details, see the LuaObject section.

Low-Level API

In addition to normal function calls, it is possible to directly call Lua's low-level API.

…
-- sample.lua

print "hello!"

wait(1.0) -- wait 1 sec

print "how are you?"

wait(1.0) -- wait 1 sec

print "goodbye!"

This code can resume the execution of the Lua script after waiting with await, as shown in the following figure. This is very useful when writing scripts to be incorporated into games.

Coroutines

Lua coroutines are represented by the LuaState type.

Coroutines can not only be used within Lua scripts, but you can also await Lua-created coroutines from C#.

-- coroutine.lua

 local co = coroutine.create(function()
    for i = 1, 10 do
        print("lua:", coroutine.yield(i - 1))
    end
end)

return co
var results = await state.DoFileAsync("coroutine.lua");
var co = results[0].Read();
var stack = new LuaStack();
for (int i = 0; i  1)
    {
        Console.WriteLine(stack[1]);
    }

    stack.Clear();
    stack.Push(i);
}

LuaObject

By applying the [LuaObject] attribute, you can create custom classes that run within Lua. Adding this attribute to a class that you wish to use in Lua allows the Source Generator to automatically generate the code required for interaction from Lua.

The following is an example implementation of a wrapper class for System.Numerics.Vector3 that can be used in Lua:

…
-- vector3_sample.lua

local v1 = Vector3.create(1, 2, 3)
-- 1  2  3
print(v1.x, v1.y, v1.z)

local v2 = v1:normalized()
-- 0.26726123690605164  0.5345224738121033  0.8017836809158325
print(v2.x, v2.y, v2.z)

The types of fields/properties with the [LuaMember] attribute, as well as the argument and return types of methods, must be either LuaValue or convertible to/from LuaValue.

Return types such as void, Task/Task, ValueTask/ValueTask, UniTask/UniTask, and Awaitable/Awaitable are also supported.

If the type is not supported, the Source Generator will output a compile-time error.

LuaMetamethod

By adding the [LuaMetamethod] attribute, you can designate a C# method to be used as a Lua metamethod.

Here is an example that adds the __add, __sub, and __tostring metamethods to the LuaVector3 class:

…
local v1 = Vector3.create(1, 1, 1)
local v2 = Vector3.create(2, 2, 2)

print(v1) -- 
print(v2) -- 

print(v1 + v2) -- 
print(v1 - v2) -- 

[!NOTE]
__index and __newindex cannot be set as they are used internally by the code generated by [LuaObject].

Module Loading

In Lua, you can load modules using the require function. In regular Lua, modules are managed by searchers within the package.searchers function list. In addition to this, Lua-CSharp provides ILuaModuleLoader as a module loading mechanism.

[!NOTE] Module resolution by ILuaModuleLoader is performed before package.searchers.

public interface ILuaModuleLoader
{
    bool Exists(string moduleName);
    ValueTask LoadAsync(string moduleName, CancellationToken cancellationToken = default);
}

You can set the LuaState.ModuleLoader to change how modules are loaded.

You can also combine multiple loaders using CompositeModuleLoader.Create(loader1, loader2, ...).

state.ModuleLoader = CompositeModuleLoader.Create(
    new CustomModuleLoader1(),
    new CustomModuleLoader2()
);

Loaded modules are cached in the package.loaded table, just like regular Lua. This can be accessed via LuaState.LoadedModules.

LuaPlatform

In Lua-CSharp, environment abstraction is provided as LuaPlatform for sandboxing.

var platform = new LuaPlatform(
    FileSystem: new FileSystem(),
    OsEnvironment: new SystemOsEnvironment(),
    StandardIO: new ConsoleStandardIO(),
    TimeProvider: TimeProvider.System);

var state = LuaState.Create(platform);

These are used for require, print, dofile, and the os module.

Exception Handling

Lua script runtime exceptions throw exceptions that inherit from LuaException. You can catch these to handle errors during execution.

try
{
    await state.DoFileAsync("filename.lua");
}
catch (LuaCompileException)
{
    // Handle parsing errors
}
catch (LuaRuntimeException)
{
    // Handle runtime exceptions
}
catch(OperationCanceledException)
{
    // Handle cancel exceptions
    // LuaCanceledException allows you to get the cancellation point within Lua.
}

Lua.Unity

Lua-CSharp can also be used in Unity (works with both Mono and IL2CPP).

Requirements

  • Unity 2021.3 or higher

Installation

  1. Install NugetForUnity.

  2. Open the NuGet window by going to NuGet > Manage NuGet Packages, search for the LuaCSharp package, and install it.

  3. Open the Package Manager window by selecting Window > Package Manager, then click on [+] > Add package from git URL and enter the following URL:

    https://github.com/nuskey8/Lua-CSharp.git?path=src/Lua.Unity/Assets/Lua.Unity
    

LuaImporter / LuaAsset

By introducing Lua.Unity, files with the .lua extension can be treated as LuaAsset.

These assets can be used similarly to a standard TextAsset.

var asset = Resources.Load("example");
await state.DoStringAsync(asset.Text, ct);

Resources(Addressables)ModuleLoader

Implementations of ILuaModuleLoader that utilize either Resources or Addressables internally are also provided.

// Use Resources for module loading
state.ModuleLoader = new ResourcesModuleLoader();

// Use Addressables for module loading (requires the Addressables package)
state.ModuleLoader = new AddressablesModuleLoader();

UnityStandardIO / UnityApplicationOsEnvironment

UnityStandardIO and UnityApplicationOsEnvironment are provided as LuaPlatform elements for Unity.

var platform = new LuaPlatform(
    FileSystem: new FileSystem(),
    OsEnvironment: new UnityApplicationOsEnvironment(), // OsEnvironment for Unity
    StandardIO: new UnityStandardIO(), // StandardIO for Unity
    TimeProvider: TimeProvider.System);
var state = LuaState.C

Issues· 0 open

View all issuesOpen on GitHub

No open issues yet, or sync has not completed.

> Tags

C#

No comments yet. Be the first to share.

> Details

PublishedAug 1, 2026
UpdatedSep 17, 2026
Category编程语言
PricingOpen source

> Related tools

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言