Lua Framework [Confirmed: works in iOS!]

Hello everyone,

I’ve just released a script asset, which is an add-on for MoonSharp, a brand new Lua - Unity/C# bridging library developed by a friend of mine. It allows reading Lua data into Unity in a way that’s faster, easier and more intuitive than anything previously available, and works on both Unity and Unity Pro!

If you’ve ever wanted to use Lua to help build your game or add modding elements, it’s now easier than ever. I’m using this asset myself in a game under development, a Legend Of Grimrock kind-of oldschool RPG, which uses Lua for asset definitions and modding the same way LoG does.

Asset Store Link: Unity Asset Store - The Best Assets for Game Making

Description :

Lua Framework allows you to easily and automatically convert data defined in the Lua script language to .NET objects, and vice-versa. It works like XML or JSON readers, but instead of a markup language, you now have access to a powerful programming language to define your game or application’s logic. Like many top-selling games did, choosing Lua can greatly streamline the game design process and most importantly, allow easy-to-implement modding capacities.

Lua Framework is built on the power of MoonSharp, a modern and free .NET implementation of the Lua language. As opposed to previous .NET to Lua bridges such as LuaInterface, NLua or UniLua, MoonSharp provides a very intuitive user experience with fast learning curve, fast performance, is regularly updated, supports latest Lua 5.2, and supports Unity’s Mono implementation of the .NET language out of the box, on all Unity versions and licenses, including iOS. You can learn more about MoonSharp and download it at moonsharp.org.

For now, the Lua Framework has two main modules: LuaReader and LuaWriter. LuaReader automatically maps Lua variables and tables to .NET objects. LuaWriter creates a Lua script representation of .NET objects. Currently supported types are:

  • Built-in types: bool, int, float, double, string, byte & decimal;
  • Enums;
  • Unity-specific structs: Color, Color32, Rect, Vector2, Vector3 & Vector4;
  • Lua functions (closures)
  • ANY custom classes with public properties;
  • One-dimensional or two-dimensional arrays of any supported type;
  • Generic Lists or Dictionaries of any supported type;
  • Any possible nesting, for example List<Dictionary<string, Vector3>>.

The code for the Lua Framework is clean and professional, performance-optimized, with full intellisense support.

Manual:

You can download the complete manual to get a better understanding of how this asset works:
Lua Framework Manual V 1.0.pdf.

Example:

But as a quick example of what this can do, Lua Framework can map the following Lua code:

defineEnemy{
name = “Bandit”,
health = 50,
attackPower = 3.5,
}

defineEnemy{
name = “Bandit Leader”,
health = 125,
attackPower = 5,
}
To this C# class:
public class Enemy
{
public string name { get; set;}
public int health { get; set;}
public float attackPower { get; set;}
}

With one simple function call (called by the Lua defineEnemy function, see manual for details):

Enemy enemy = LuaReader.Read<Enemy>(luaTable);

Without the need of any further attributes, casting or manual parsing and reading of lua tables/data. The equivalent code with NLua would be:

Enemy enemy = new Enemy();
enemy.name = (string) luaTable[name];
enemy.health = (int) (double) luaTable[health];
enemy.attackPower = (float) (double) luaTable[attackPower];

Which is longer of course as Lua Framework takes care of all the castings, but also less flexible: if you decide to change your Enemy class in the future, by adding, renaming or removing properties, you need to change the parsing code. Also, the above will raise errors if your lua table happens to miss a property, requiring you to add a lot more code if you want some properties to be optional, or safety against user scripts for mods.


Questions, comments, feature requests? Don’t hesitate to post, I’ll be glad to answer and incorporate anything you need in future updates.

1 Like

Does this happen to work on iOS?

I haven’t tested it personally, but technically I don’t see why it shouldn’t, as MoonSharp’s dll is entirely managed code (that’s also what makes it work on Unity “free”). At least the developer stated so here: http://answers.unity3d.com/questions/373638/interpreter-script-language-that-can-be-used-ingam.html?sort=oldest

And you don’t need to install any additional Lua .dlls which are platform-specific.

I looked closer at your sample above and I see that you’re doing manual initialization and binding of the lua to project objects. That should work fine. At first glance I thought it was using reflection to do dynamic binding, and that doesn’t work on iOS.

I’ll have to give it a try. :slight_smile:

My asset DOES use Reflection to dynamically map Lua data to project objects by enumerating through their properties, but it does so on types known ahead at compile-time, without generating any code at runtime with Reflection.Emit. According to my research (here: http://jonathanwagner.com/blog/2013/05/02/the-secret-guide-to-mono-runtime-limitations-for-unity-on-ios/ and here: Limitations of Xamarin.iOS - Xamarin | Microsoft Learn) this IS supported just fine on iOS.

Just to make it clear, this “auto-binding” is one of the main points of this asset. If you wish, you can download MoonSharp for free and use it like this:

Enemy enemy = new Enemy();
enemy.name = luaTable[“name”];
enemy.health = (int) luaTable[“health”];
enemy.attackPower = (float) luaTable[“attackPower”];

But my framework allows you to simplify it to (Enemy type is specified at compile-time):

**Enemy** enemy = **LuaReader**.Read<**Enemy**>(luaTable);

Where it enumerates on Enemy’s properties, looks if the table contains them, and makes the necessary casts. It also works recursively, so if your Enemy had a property like

**Attack** attack { **get**; **set**; }

which is it’s own class, it would work just fine and map any sub- or sub-sub-classes in whatever structure you have.

Also, by support of Unity structs, you can do:

Standard MoonSharp:

**Vector3** vec3 = **new Vector3**((**float**) luaTable[1], (**float**) luaTable[2], (**float**) luaTable[3]);

MoonSharp + LuaFramework:

**Vector3** vec3 = **LuaReader**.Read<**Vector3**>(luaTable);

With the avantage that it handles situations like if for example your lua table only contained 2 values instead of 3, and it auto-handles it if you have custom classes which have Vector3 (or other supported Unity Types) properties.

And then there’s the LuaWriter counterpart which allows you to serialize objects to Lua scripts, you can check the manual for examples.

Hope this makes it clearer!

Very nice, and very useful. And exactly how binding to Lua should work. :slight_smile: I haven’t used a managed lua system yet, but last time I messed with Lua it was pretty messy to get it all hooked up. I’d love to clean that up. I was dreading doing manual binding to a non-managed Lua for an upcoming game, so this asset is very timely.

It’s been a while since I tried to use reflection on iOS in Xamarin, and I don’t recall what I was trying to accomplish with it. I do remember that it took several hours to figure out another way to accomplish the same thing and rewrite the code to work that other way instead of the original few lines that just used reflection. It was in the very early days of Xamarin, though, so maybe whatever it was that I tried to do before would work now. I haven’t ever done anything directly with the DLR and Emit, so I know it wasn’t that. :slight_smile: In non-iOS stuff, I use a lot of reflection to get attributes and do stuff with some DAL classes I’ve built, so it was probably related to that.

Sounds like your asset is something I’ll want to snag for the regular non-game stuff I do, too. :slight_smile:

Hey, just as a quick update, I got in touch with the MoonSharp developper, and he says that while the MoonSharp code “should” work fine on iOS, users have reported problems due to ANTLR, the .dll MoonSharp uses for parsing lua scripts. He says he will see if he can get an iOS device to test things out.

Does this work with unity 5.0?

Hi,

Absolutely, I just tested it and it works great with Unity 5. The MoonSharp developper has also managed to remove the need for the ANTRL .dll… I tested a beta build which now makes MoonSharp work way faster and could actually make it work on iOS! Crossing fingers…

Jumping in… another friend of mine/us will hopefully be testing the new MoonSharp build on iOS in the weekend. It already works wonderfully under Linux with mono --full-aot which should be equivalent of what Unity does for iOS but I need more testing :wink:

I can confirm :

MoonSharp 0.9.0 runs on iOS !

Hi everyone,

I’ve just released a small update to the Lua Framework, it adds support for reading Lua functions (closures) to the C# side, and for adding custom readers.

Custom readers allow you to format your Lua data in any way you like, and also provides support for custom structs. For example, standard Lua Framework behavior reads this lua:

person = {
name = “John”,
age = 26,
}

Into this C# class:

public class Person
{
public string name { get; set; }
public int age { get; set; }
}

But you could also define a custom reader like this (C#):

**LuaReader**.AddCustomReader(typeof(**Person**), dynValue =>
{
var luaTable = dynValue.Table;
return new Person{
name = LuaReader.Read(luaTable.Get(1)),
age = LuaReader.Read(luaTable.Get(2))
};
});

And then format your Lua tables like this:

person = {“John”, 26}
person2 = {“Maria”, 31}
person3 = {“Paul”, 17}

For more details, see the updated manual.

Asset Store link: Unity Asset Store - The Best Assets for Game Making
Manual v1.1: http://www.georgesdimitrov.com/wp-content/uploads/Lua-Framework-Manual-V1.1.pdf

I’m thinking about “smart” config file that looks like:

version =“1.0.19”
health =10
attackPower =1

–Read User from C#
if User.level > 20 then Ads.enabled =false end

I’m confused if Apple would approve such use. It is specified that only JavascriptCore is allowed etc etc but we see things like codea.io. That makes me wander can se use moonsharp based thing when making production apps? Any thoughts on that?

I’m especially interested in where is the line between code and data…

Hi,

There shouldn’t be any problem doing what you want to do above. The easiest thing would be to put your .lua code as a text file in a Resources folder and load/execute it at runtime, but there’s also the streaming assets option: http://docs.unity3d.com/Manual/StreamingAssets.html.

You should read on how moonsharp passes C# objects to Lua here: MoonSharp.

For your purposes, just the first example, titled “Keep it simple” is ample enough:

  1. Tag your User and Ads classes with a [MoonSharpUserData] attribute
  2. Call UserData.RegisterAssembly(); somewhere once to initialize the C#-Lua link for classes marked UserData
  3. Create a new Script object, like var lua = new Script();
  4. Register your objects in the lua Script:
    lua.Globals["User"] = user; ← where user is a reference to your user.
    lua.Globals["Ads"] = ads; ← where ads is a reference to your ads.
  5. Get the text for your script, for example var configScript = Resources.Load<TextAsset>("config.lua").text; ← Actual file is named config.lua.txt in the resources folder because Unity wants .txt files.
  6. Run the script: lua.DoString(configScript);

Hi guys,

Just a quick update on the iOS status.

I got an iPad last week and managed today to build and run the demo scene of Lua Framework on my iOS device.

Conclusion: Lua Framework works 100% perfectly on an iPad Air 2 with iOS 9 installed. :slight_smile:

Hi George,

Thanks for the post. I had no problem integrating Lua and exposing our custom data. Good to hear the compatibility with iOS9.

Happy to hear that! If you’re using the asset and are happy with it, consider submitting a review to the store, it always helps future users… :slight_smile:

Hey, does this asset support all the intricacies of regular Lua coroutines? How nicely does it play with Unity’s coroutines and C# code?
How difficult would it be for me to do something like this:

co = coroutine.create(function (i)
    local a = coroutine.yield(i);
    local b = coroutine.yield(i, a);
    local c = coroutine.yield(i, a, b);
    return i, a, b, c;
end);
IEnumerator CallLua () {
    //Somehow call coroutine.resume(co, 0);
    //Somehow get all the results of the call: 0
    yield return null;
    //Somehow call coroutine.resume(co, 1);
    //Somehow get all the results of the call: 0, 1
    yield return null;
    //Somehow call coroutine.resume(co, 2);
    //Somehow get all the results of the call: 0, 1, 2
    yield return null;
    //etc.
}
void Start () {
    StartCoroutine(CallLua());
}
1 Like

Hi!

Moonsharp supports coroutines entierly, and even handles them even better than stock Lua: MoonSharp

As I personnaly haven’t played much with coroutines on the Lua side, I haven’t implemented specific support for coroutines in Lua Framework beyond what Moonsharp already allows you to do. But this means you should probably be able to use Moonsharp’s built-in coroutine support to do what you wish above, while still using the Lua Framework auto type-mapping capabilities.

I will do some tests in the coming days to see how Lua coroutines work with Unity coroutines, and see if there is something I could provide in my framework to automate the process of creating and handling these.

I’m kinda stuck for couple of hours already figuring best way to serialize Table object. Just letting you know it would be great to have something that could handle it automatically.

It would be awesome if there was easy way to serialize table object that can contain nested table objects (be it dictionary or list). WriteLine function sadly writes everything as a string, and I cant WriteObject because I use Tables and not custom objects that use built in types. Explanation why I do things such a way are below:

I have custom component classes (non mono behaviours) that take only Table object into constructor. Lua scripts define my game entity components in tables and create them in c# with simple add method that takes table as argument. Scripts that contain game logic which I want to be moddable use entity references to access variables from tables in components. Its all working pretty well and i’m happy with end result. I’m creating turn based game so execution speed while important has lower priority than game modding capabilities.

@georgesdimitrov do you have any suggestions or maybe you could consider supporting serializing table as this asset is amazing what it does - except this edge case. I could of course not think about something that may be obvious to you as I’m still learning my ways around c# (I have years of experience in other tech - languages closer to lua than c# though), so maybe afterall writing tables containing all those DynValue objects back as lua objects is piece of cake and I just cant figure it out :slight_smile: