I’ve recently had a need for user-level scripting, and have reimplemented an amalgamation of various open source Lua libraries which I used about a year ago. I’m wondering whether it’s the kind of thing other people have a need for.
It uses a library called LuaInterface, which allows a huge amount of bidirectional interoperation. For example, you can make a behaviour’s FixedUpdate method call a Lua function, as well as read and write Lua variables. You can pass delegates to the Lua code, which can then call them directly, and the most significant thing LuaInterface provides is full access to .NET libraries - including UnityEngine, for example. So your Lua code can do pretty much anything your C# code can do, including creating GameObjects, moving them around, adding and removing components, and so on.
The Lua interpreter is a full C# implementation (KopiLua), so it should work on all platforms, but it’s not written for speed out of the box. There’s a lot of room for optimization, but of course it will inevitably be slower than doing the same work in C#. Nevertheless, if you need dynamic scripting it might be a good solution.
I’m interested in use cases - I guess obvious ones are things like modding, and some games might be built around user-level scripting. My own use case is not really a game, but requires the user to be able to write short scripts to move objects around (a bit like Logo, in a way!) and using Lua for this feels like a good fit as it has a simple syntax for simple code, but also allows writing much more complex code if the user needs to.
Getting the script data into the game is another matter - currently I’m using HTML form fields and Javascript to inject the script data into the Unity player, but native apps obviously have more flexibility there.
I could think of some situations where this might be useful, yeah. I don’t have a current need for it, but I could see myself wanting it in the future, maybe.
Have you looked at the asset store? I think one guy implemented something like this, but it only works on Windows. It would be awesome if you could make it works on both Windos and Mac!
As for usecases, I think using Lua will really help with a lot of things. Level creation is one thing for sure. Using lua files to create levels would be much easier to fix and patch the game. Instead of having to upload the whole big executable file, we can upload the fixed lua files.
I need a solution that works on both Mac and PC, so I’m currently using the python one on asset store, and the javascript with Jurassic Engine.
You don’t have to do that anyway; the executable for Unity is fixed and doesn’t change with your scripts. If you look in the data for a game you will see things like (depending on what language(s) you used) “Assembly - UnityScript.dll” and “Assembly - CSharp - first pass.dll”, which are typically a few dozen to a few hundred KB depending on how big your scripts are.
As the interpreter has been ported to C#, it should work on any platform - I’ve tested on Mac, PC, and web player, but I don’t have licenses for iOS etc.
Initially the scene is empty, but if you press “Send Code” it will send the sample code from the web page to the app, which executes it in the Lua interpreter, and it will create and animate a cube. Note that you can do pretty much anything you like in the Lua code. The code block is executed as soon as you send it, and any update(dt) function it defines gets called from a FixedUpdate method in a MonoBehaviour.
This is much more useful than my brainfuck interpreter
Do you intend to release your code?
Edit: Crashing the code is fun - it makes the a new block, freezing it in position and rotation [as they are determined by time]- leading to a colorful block tower!
You’re not really crashing it, it’s just that every time you press the button the script makes a new cube, overwriting the ‘cube’ variable, and so the update() function no longer moves the old cube around. If you delete or comment out that line then you can just change the update() function iteratively without constantly making new cubes. This is all just artifacts of the silly way I hooked it up for the demo.
I’ll check the licences of the libraries, but I doubt there are any restrictions so I can probably put it on the asset store or a web site sometime.
The Lua interpreter on the asset store looks similar to this - it’s also based on LuaInterface, but with the standard C back end. It’s probably more efficient as a result. It may be possible to extend that one to support both back ends, depending on platform.
Wow! Thank you so much for this. Is there anywhere we can find out more about these information? For example, changing some value inside the prefab, what would that affect the output?
Awesome! And I’m really happy to hear that it works on Mac and PC. Really looking forward to this!
I should clarify that I was trying to crash it [assigning a string to a vector] but you’re correct, the activity I observed appears to have nothing to do with the bug I introduced.
Looks very good !
I am looking forward for the source code.
Is there a way to limit the authorized instructions ?
Like block access to Camera…
Even it would be possible by parsing the lua script with string function, I am asking for an automatic way.
I think most of the code is under the MIT license, so it should be OK to publish it. At present KopiLua needs to be compiled in Visual Studio, as it requires some defines to be set; these could be replicated at the top of each source file, allowing all the source to be used directly in Unity. As it stands I’m just copying the DLLs into the Unity project though, which works fine - it doesn’t make much difference really. You could extract them from the WebPlayer.unity3d file I uploaded if you want to get a head start.
By default LuaInterface defines a “luanet” variable in the Lua interpreter, which Lua code can use to access arbitrary assemblies - this is the bit that lets the code do whatever it likes. But you can undefine it, e.g.
var L = new Lua();
L["luanet"] = null;
However, I believe if you allow direct access to any .NET type (e.g. a GameObject) then it’s possible for the script to access arbitrary things from the same assembly, and other assemblies if things cascade. So if you want to be sure about these things, you might want to not use LuaInterface at all - just use KopiLua directly. You’d lose all the magic that you didn’t want, and could be more confident that the Lua code could only fiddle with things you’d explicitly provided to it.
I would be interested in this since I use LuaInterface and although I can bring the the LuaInterface library just fine in the projects, I can’t create a LUA hook without object not defined type errors and other errors from the Unity engine, but this is with 3.5.0.
I’ve uploaded a zip here, including source code and the demo Unity project I’m using, with precompiled DLLs. It’s pretty shabby, but I figured it was better to upload something than nothing!
Thanks! I’m looking forward to trying this out in my project.
A useful trick for reloading Lua files at runtime is to create objects only if they haven’t yet been created. That way you can make changes to the code while it’s running and get immediate results without spawning multiples.
For example, change the first line of code in your web example to this:
cube = cube or UnityEngine.GameObject.CreatePrimitive(UnityEngine.PrimitiveType.Cube)
Then you can mess with the update function and resend it while the game runs.
I added some exception handling and access to audio spectrum data. The result is a little livecoding website where you can code your own music visualizer while you watch it take shape.
Could you elaborate on this? How would I just use KopiLua with a unity project, and if you have time, could you provide an example of implementing it? (as far as explicity telling lua what it can do)
I’m looking to implement a programming language within unity, but don’t need it to even have anything to do with UnityEngine, just a totally separate and custom language, who’s commands are then taken and then processed by Unity.
I’m also not looking for this to be real-time, but scripts that have already been written and are simply loaded and run in unity.
Perhaps this isn’t the right application for LuaInterface?
Very nice! Sorry I didn’t see it earlier, I find the forum’s email notifications are a bit unreliable.
How did you capture ‘print’ output - any special way? Also what did you mean about exception handling? I didn’t really follow the way the Lua wrappers deal with this - the whole call vs pcall thing. For debugging I often set the #defines to make it just throw exceptions as soon as errors occur instead of passing them up through the API - much easier to trace that way.