game engines: using ALL the languages

In the 1.0/long term version of my engine, I designed the core runtime to expose it's API in such a way that it would be agnostic to a scripting language. This is a short post on how that looks, when you connect the dots.

This post needs a thanks to a friend Jeff Ward who helped me with the dart embedding, and clarified some of my misconceptions/lack of clarity about embedding mono.

I've chosen wren for several reasons as the default language in my engine. That post includes a lot of rationale, but near the end points out that you'll be able to use any language later. I was validating some assumptions earlier today and figured hey, why not bind <x> - it'll be quick? And a few hours later.... x was not alone.

Turns out I could bind rust, c# (mono), c++, js, lua, dart, python and swift in less than a day. It's not the entire API, but the foundations are there (the rest can largely be generated). This also comes back to the data oriented API too, because things are all static functions and primitives it's a bunch easier.

Here's how the log looks when they're all loaded up:

Here's how the dependencies look after:

sometimes simple

I was really surprised how simple it was in some languages, like c# with mono can handle a c function pointer directly. This is great, because that's how the API is defined. This is true of rust and swift, they both have direct access to the endpoints. lua and js (via for example have generic function callbacks, where you unpack the args and forward them along.

This is the C# connection to the C API.

And then on the c# side:

sometimes frustrating

The dart sdk pulled down around 5.5gb of... stuff. It then built for a long while and the folder was around 6.5gb before I saw any usable files. I don't know why dart implies it's designed to be embedded, a lot of the header files in the embedding api reference internal header files, use unportable functions (_strdup) and more. It's wild.

Python has dependencies on a lot of implicit binaries. With cffi and cpython or pypy it has to reach the python runtime, the cffi runtime and who knows what else (in terms of standard lib?). Even the cffi docs complain the entire thing is a mess... I hate dependencies, and wouldn't want the end user to have to install python or anything. Maybe those can somehow be put alongside the binary all together, but I have no idea atm.

user plugin api

On the user end, the workflow should ideally be the same. They get a consistent interface to the engine API (idiomatic to the language to some extent) and they all feel similar.

Here's how it works in rust, c#, python (but you can imagine the rest, they're all very similar by design).

That's it for today

I'll go into more details in the future, and if you have questions feel free to send them my way.