Implementing scripting in a game engine
What would be the best way to implement scripting in a game engine? I've been looking at reflection and runtime code compilation but I wasn't sure if they would give the user access to the engine's libraries. I was also thinking of implementing my own custom language like what Godot does, but my engine is so simple that I think it would be overkill.
I'd like to do something similar to how big engines like Unity and Godot do it (attaching scripts to objects), is there an effective way to do that?
21 Replies
Maybe I could achieve the desired outcome by implementing Lua or python support?
lua is common for ingame scripting
you can do C# but you have to be very careful and basically whitelist exactly what types/members they're allowed to use, and without sandboxing they could easily break things
I think I've come up with a potential idea. My engine can just export scenes that the (sort of separate) libraries can make sense of
Do you know of any libraries that can link the two together?
not personally, you could ask #game-dev
ive not used it a ton, but Moonsharp might be a good option https://github.com/moonsharp-devs/moonsharp
GitHub
GitHub - moonsharp-devs/moonsharp: An interpreter for the Lua langu...
An interpreter for the Lua language, written entirely in C# for the .NET, Mono, Xamarin and Unity3D platforms, including handy remote debugger facilities. - moonsharp-devs/moonsharp
I'll research moonsharp, it seems promising!
I'll see if they have any other libraries along with moonsharp
space engineers has ingame blocks where you can execute c# code
yes and they do the thing i suggested for that
and afaik they frequently cause performance issues and have unfixable exploits due to the nature of C#
I think I'm going to try this first, and if it doesn't work I'll implement either Moonsharp / NLua or some python equivalent
What about using a WASM sandbox of assemblies? Is that already a thing or still in preview?
stevensandersonuk
YouTube
DotNetIsolator: an experimental package for running .NET code in an...
A quick overview and demo of an experimental new .NET package that can create isolated .NET runtime instances for running code in a sandbox.
If it's a thing already I might give it a shot. Would it give the user access to built-in libraries in my engine?
I believe you have fine control over the types available to consumers. I didn't look into it that much but I assume it is possible.
I'll do some more research, this seems promising
Unfortunately I couldn't get anything that had to do with Roslyn to work (didn't even install properly), so I'll have to do more looking around
Maybe NLua is my only option for now if absolutely nothing else is working at the moment
I could help you set it up. From my experience it seems straightforward. But I understand if by this point it would seem like too much effort to you.
That'd be cool
How much of a pain is it to set up normally?
Here's an MVP to get you started. I hope this helps.
First, we create our source code. This could be a user supplied source or from whereever.
Next, we compile to an in-memory stream using roslyn.
Then, we load the fresh assembly and get the relevant plugin type. You could do this using a marker attribute, for example.
Afterwards, we set up the WASM isolation and in particular grant it access to the standard output of the host app (for example).
Lastly, we invoke the plugin entry method and provide it with an argument.
The plugin interface is defined in the same project as the executing code but we could move it to a dedicated library as well.
I'm listing the required packages at the end there also.
If you have any questions, shoot
I think I'll experiment with this before I implement it into my engine, thanks for the help!
Would you recommend moonsharp over NLua?
NLua is giving my quite some trouble just getting basic things to work properly
And it's got like no documentation either
ive not worked with either enough to have an informed opinion. I did like working with mmoonsharp though
I've just tried MoonSharp and it's already seeming to work better, though I'll still need to test it
Sorry if this is a dumb question, but do you know how I could dynamically register methods?
I'd like to be able to give users access to Raylib functions
I read the documentation (https://www.moonsharp.org/callback.html), but this just seems like I'd have to hard code each and every function