Rust(lang) in Unity3D

How to use Unity’s Native Plugin interface to call fast, safe code in Rust

Jim Fleming
Jim Fleming

--

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:

Check out this guide for info on important parts like #[no_mangle] and extern.

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:

See here for more information on the manifest file format with attention to compiling libraries.

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):

For more information on Unity’s native plugin interface, see here.

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

  1. Complete project for Unity5: https://github.com/jimfleming/unity-to-rust
  2. Rust Once, Run Everywhere: http://blog.rust-lang.org/2015/04/24/Rust-Once-Run-Everywhere.html
  3. Rust FFI documentation: https://doc.rust-lang.org/book/ffi.html
  4. Rust FFI examples for other languages (Node, Python, Ruby, C, etc.): https://github.com/alexcrichton/rust-ffi-examples
  5. Cargo manifest documentation for dynamic and static libraries: http://doc.crates.io/manifest.html#building-dynamic-or-static-libraries
  6. Unity Native Plugins documentation: http://docs.unity3d.com/Manual/NativePlugins.html

--

--