Lua-CSharp Documentation

repository·main·Indexed 21 days ago

https://github.com/nuskey8/lua-csharp

A high-performance Lua 5.2 interpreter implemented entirely in C# for .NET applications and Unity (Mono and IL2CPP). It features low allocation, seamless interop via [LuaObject] and [LuaMember] attributes, and async/await integration. The library supports custom module loading through ILuaModuleLoader, sandboxing via LuaPlatform, and a dedicated Unity package (com.nuskey8.lua.unity) that introduces LuaAsset for treating .lua files as Unity assets.

Tokens
8K
Snippets
30
Records
37
Agent score
73%

What's inside Lua-CSharp

  1. Customize module loading with ILuaModuleLoader

    main

    Lua-CSharp provides the ILuaModuleLoader interface to control how require resolves modules. This mechanism runs before the standard Lua package.searchers.

    • LuaState.ModuleLoader: Set this property to provide a custom loader.
    • FileModuleLoader: The default implementation that loads modules from Lua files.
    • CompositeModuleLoader.Create(loader1, loader2, ...): Allows combining multiple loaders into a single search chain.
    • LuaState.LoadedModules: Provides access to the package.loaded table for cached modules.
    public interface ILuaModuleLoader
    {
        bool Exists(string moduleName);
        ValueTask<LuaModule> LoadAsync(string moduleName, CancellationToken cancellationToken = default);
    }
    
    // Usage example
    state.ModuleLoader = CompositeModuleLoader.Create(
        new CustomModuleLoader1(),
        new CustomModuleLoader2()
    );
  2. Integrate async/await with Lua functions

    main

    Since LuaFunction is asynchronous, you can define C# functions that perform asynchronous work (like Task.Delay) and await them within a Lua script. This is particularly useful for game scripting where you need to pause execution without blocking the main thread.

    // Define a function that waits for a given number of seconds
    state.Environment["wait"] = new LuaFunction(async (context, ct) =>
    {
        var sec = context.GetArgument<double>(0);
        await Task.Delay(TimeSpan.FromSeconds(sec));
        return context.Return();
    });
    
    // Lua script can now use: wait(1.0)
    await state.DoFileAsync("sample.lua");
  3. Important differences in Lua-CSharp (Encoding and GC)

    main

    Because Lua-CSharp is implemented in .NET, it behaves differently than standard C Lua in two key areas:

    1. Character Encoding (UTF-16) Lua-CSharp uses UTF-16. Standard Lua assumes single-byte encoding. Consequently, string length functions like string.len() will return the number of UTF-16 code units rather than bytes. For example, string.len("あいうえお") will return 5 in Lua-CSharp, whereas standard Lua would return 15.

    2. Garbage Collection Lua-CSharp relies on the .NET Garbage Collector. While collectgarbage() is available, it is a wrapper for .NET GC methods and may not behave identically to the deterministic behavior of the C Lua garbage collector.

  4. Important compatibility notes for Lua-CSharp

    main

    Because Lua-CSharp is implemented in C#, it differs from standard C Lua implementations in two key areas:

    1. UTF-16 Character Encoding: Strings are handled as UTF-16. Functions in the string library operate on UTF-16 code units. For example, string.len("あいうえお") will return 5 instead of the byte length expected in standard Lua.
    2. Garbage Collection: Memory management relies on the .NET GC. Calling collectgarbage() is equivalent to GC.Collect() and its arguments are ignored. Weak tables (week tables) are not supported.
  5. Use LuaAsset in Unity

    main

    The Lua.Unity package introduces LuaAsset, allowing .lua files to be treated as assets in the Unity Editor, similar to TextAsset. You can load them via Resources.Load and execute them using DoStringAsync.

    var asset = Resources.Load<LuaAsset>("example");
    await state.DoStringAsync(asset.Text, ct);
  6. Configure LuaPlatform for Unity

    main

    When using Lua-CSharp in Unity, use the provided UnityStandardIO and UnityApplicationOsEnvironment to ensure Lua commands map correctly to Unity behavior:

    • UnityStandardIO: Redirects print to Debug.Log().
    • UnityApplicationOsEnvironment: Maps environment variables to a Dictionary and makes os.exit() call Application.Quit().

    Additionally, use ResourcesModuleLoader or AddressablesModuleLoader to allow Lua's require to find Unity assets.

    var platform = new LuaPlatform(
        FileSystem: new FileSystem(),
        OsEnvironment: new UnityApplicationOsEnvironment(),
        StandardIO: new UnityStandardIO(),
        TimeProvider: TimeProvider.System);
    
    var state = LuaState.Create(platform);
    
    // To load assets via Unity's systems:
    state.ModuleLoader = new ResourcesModuleLoader(); // or new AddressablesModuleLoader();
  7. Quick Start with LuaState

    main

    The LuaState class is the entry point for the interpreter. You can create a state and execute Lua code using DoStringAsync or DoFileAsync.

    WARNING

    LuaState is not thread-safe. Do not access it from multiple threads simultaneously.

    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]);
  8. Create custom Lua objects with [LuaObject]

    main

    You can expose C# classes to Lua by applying the [LuaObject] attribute. This triggers a Source Generator to create the necessary glue code. To expose specific members, use the [LuaMember] attribute.

    Key Rules:

    • The class must be marked as partial.
    • [LuaMember] can be applied to properties, fields, and methods.
    • For methods, you can specify a custom name in the attribute (e.g., [LuaMember("x")]).
    • Static methods are accessed as standard Lua functions (e.g., Class.method()).
    • Instance methods are accessed using the colon syntax in Lua (e.g., instance:method()), where the instance is implicitly passed as the first argument.
    • Member types, arguments, and return types must be compatible with LuaValue or convertible to it.
    • Supported return types: void, Task/Task<T>, ValueTask/ValueTask<T>, UniTask/UniTask<T>, and Awaitable/Awaitable<T>.
    [LuaObject]
    public partial class LuaVector3
    {
        [LuaMember("x")]
        public float X { get; set; }
    
        [LuaMember("create")]
        public static LuaVector3 Create(float x, float y, float z) => new LuaVector3();
    
        [LuaMember("normalized")]
        public LuaVector3 Normalized() => this;
    }
    local v1 = Vector3.create(1, 2, 3)
    print(v1.x)
    
    local v2 = v1:normalized()
  9. Install Lua-CSharp in Unity

    main

    Lua-CSharp supports Unity (both Mono and IL2CPP) with Unity 2021.3 or higher. Follow these steps:

    1. Install NugetForUnity.
    2. Open the NuGet window via NuGet > Manage NuGet Packages.
    3. Search for and install the LuaCSharp package.
    4. Open the Package Manager (Window > Package Manager).
    5. Click [+] > Add package from git URL and enter: https://github.com/nuskey8/Lua-CSharp.git?path=src/Lua.Unity/Assets/Lua.Unity
  10. Handle Lua exceptions in C#

    main

    Runtime errors in Lua scripts throw exceptions that inherit from LuaException. You should catch these to prevent application crashes and handle errors gracefully.

    Common exception types:

    • LuaCompileException: Thrown during script parsing.
    • LuaRuntimeException: Thrown during script execution.
    • OperationCanceledException / LuaCanceledException: Thrown when a task is canceled, allowing you to identify the cancellation point within Lua.
    try
    {
        await state.DoFileAsync("filename.lua");
    }
    catch (LuaCompileException)
    {
        // Handle parsing errors
    }
    catch (LuaRuntimeException)
    {
        // Handle runtime exceptions
    }
  11. Install Lua-CSharp via NuGet

    main

    To use Lua-CSharp in your .NET project, you must use .NET Standard 2.1 or higher. You can install it using the .NET CLI or the Visual Studio Package Manager.

    # .NET CLI
    dotnet add package LuaCSharp
    
    # Package Manager
    Install-Package LuaCSharp