Rust(lang) in Unity3D
How to use Unity’s Native Plugin interface to call fast, safe code in Rust
Lot’s of people are excited about Rust for its applications to game development. Writing native plugins in Unity3D usually means C, C++ or Objective-C and no real memory safety within the underlying code. Now that Rust has hit 1.0 I looked into calling Rust from Unity3D and it turns out to be surprisingly simple.
I should note that this guide targets OS X, not Windows. The process should be similar, likely substituting “dll” for each “dylib”. Check the referenced Unity Native Plugin guide for Windows-specifics.
From Rust
Let’s start with two simple Rust functions that return their doubled and tripled their integer inputs, respectively:
Rust uses a simple config file to define the build output and a command-line tool called Cargo to perform the actual builds. Since Unity loads libraries dynamically we want to specify “dylib” as our “crate-type” in our Cargo manifest:
Next, we run cargo build and we’re done. Pretty much the most straightforward compile process I can imagine.
Inside our target/debug/ (or target/release/ for release builds) folder should be a file named lib<name>.dylib where name corresponds to the lib name property in the config file above.
From Unity3D
We want to copy this library into our Unity project’s Assets/Plugins folder. On OS X, Unity expects native plugin’s to have a “.bundle” extension. We can simply rename our compiled lib’s extension from “.dylib” to “.bundle”. This works because the underlying command that loads the library understands both formats.
In Unity, we create a MonoBehaviour (a regular class works too), add a static extern function interface and tag it with the DLLImport attribute pointing to the name of our library in Assets/Plugins (omitting the extension):
If all goes well, playing Unity3D should produce the following output:
Conclusion
I’ve avoided writing native plugins for my games in the past due to the inherent complications around memory handling in production code. Rust makes it easier to write fast, safe code to be run within Unity, giving us an alternative over C, C++ or Objective-C for areas of high-performance code.
If you’re interested in working with more complex types via Rust’s FFI then I’ve written a follow up on my experiences that covers object methods, structs and arrays.
I’m happy to answer any questions on Twitter: @jimmfleming
References
- Complete project for Unity5: https://github.com/jimfleming/unity-to-rust
- Rust Once, Run Everywhere: http://blog.rust-lang.org/2015/04/24/Rust-Once-Run-Everywhere.html
- Rust FFI documentation: https://doc.rust-lang.org/book/ffi.html
- Rust FFI examples for other languages (Node, Python, Ruby, C, etc.): https://github.com/alexcrichton/rust-ffi-examples
- Cargo manifest documentation for dynamic and static libraries: http://doc.crates.io/manifest.html#building-dynamic-or-static-libraries
- Unity Native Plugins documentation: http://docs.unity3d.com/Manual/NativePlugins.html