Using Native C++ in Unity

I’ve been using a lot of C++ for stuff recently, and that got me thinking, can I use c++ in Unity? First off why would we want to do this?

The obvious first answer is speed. Due to C# being an interpreted langue c++ is inherently faster. Of course, there are things like JIT that shorten the gap a lot, but in the end, c++ still is faster most of the time. Another reason to use it could be the control and freedom that c++ gives you. A c++ program is able to take advantage of lower-level and platform-specific libraries that you just can’t get with C#.

For instance, if you wanted to write your own rendering engine for Unity, you can do it using their Native Plugin Interface.

Getting Started:

Using c++ is a little bit of a hassle because we can’t just put our code into an asset file and let Unity work its black magic on it for us. Instead, we have to go through the trouble of compiling c++ libraries ourselves. There are hundreds of ways to do this, but I’m going to show you how to do it with Visual Studio since if you’re using unity there’s a good chance that you’re using it already.

First, we want to make sure that Visual Studio has the components that we need. Open Up Visual Studio Installer and click the “Modify” button on your preferred version. That’ll take you to a List of workloads, make sure that “Desktop Development with C++” is checked, and then click Modify in the bottom right corner.

This’ll install everything we need to code and build our C++ code.

Once that’s done let’s create a new CMake Visual Studio Project. I’m choosing a CMake project because it opens up the possibility of building for other platforms such as Linux down the line, it also makes it easy to switch between editors later if you want to as CMake is a very common build system.

Click next and name it something that makes sense like “UnityCppTest” then click create.

You should be greeted by a mostly blank window with a Solution Explorer looking something like this:

The first thing we’ll do is open up the CMakeLists.txt, it will be very similar to this:

# CMakeList.txt : CMake project for UnityCppTest, include source and define
# project specific logic here.
#
cmake_minimum_required (VERSION 3.8)

project ("UnityCppTest")

# Add source to this project's executable.
add_executable (UnityCppTest "UnityCppTest.cpp" "UnityCppTest.h")

# TODO: Add tests and install targets if needed.

Right now this file is telling Visual Studio to compile our code into a runnable file such a “.exe”, but what we want instead is a shared library. A shared library is a bit of code that programs can load while they’re running, instead of having to have the code included in the executable. On Windows this is a “.dll” file, and on Linux they’re “.so” files.

To do this we just change “add_executable” to “add_library” and then designate our library as a shared library by adding the SHARED keyword between the target name and sources:

# CMakeList.txt : CMake project for UnityCppTest, include source and define
# project specific logic here.
#
cmake_minimum_required (VERSION 3.8)

project ("UnityCppTest")

# Add source to this project's library.
add_library (UnityCppTest SHARED "UnityCppTest.cpp" "UnityCppTest.h")

# TODO: Add tests and install targets if needed.

Now we can get to writing our c++ code! Open up the “.cpp” file and delete the main function, we only need that for executables. Now let’s write our own function:

extern "C" __declspec(dllexport) int testFunciton()
{
	return 42;
};

The “extern “C” __declspec(dllexport)” bit at the beginning tells the compiler that we want this function to be callable from outside our shared library, basically like marking a variable public in a class, but for libraries.

Now that we have our function we need to compile this and copy the built library into Unity. First let’s make sure that our CMake changes are in effect. Right-click the CMakeLists.txt file in the Solution Explorer and click “Configure UnityCppTest”. Now that our settings are applied go to the Build tab on the top bar and select “Build All” or press F6. In the console window, you should see that the build was successful. Now if you navigate to the build folder in the Visual Studio project you should find a “UnityCppTest.dll” file. At this point we’re done with the c++ side, I suggest looking into things like Debug and Release builds later but I’m not covering them here for now.

The Unity Side

Take that .dll file we just generated and copy it to anywhere inside the assets folder of your Unity project. Unity will automatically handle importing it for us from this point on. I will note that if you want to change or update the .dll in any way you will have to close unity as it doesn’t ever unload .dlls.

To use our test function we need to create a Monobehaviour to use it. I created an empty object in my scene and added a CppTestMonobehaviour to it:

public class CppTestMonobehaviour : MonoBehaviour
{
    [DllImport("UnityTestCpp")]
    private static extern int testFunction();

    // Start is called before the first frame update
    void Start()
    {
        Debug.Log(testFunction());
    }
}

The [DllImport()] tells unity where the function is located and we declare it as static because it doesn’t have any relation to any classes.

If you run it at this point you should see a 42 printed out to the console, success!

Trouble Shooting

Here are some things I ran into when I was getting this working:

If you get a DLL not found error make sure that in the C# you spelled and capitalized the .dlls name correctly but didn’t include “.dll”

If you get an “entry point not found” this means that Unity can’t find a function that matches the one you declared in your C#. Make sure that in the .cpp file you put “extern “C” __declspec(dllexport)” before your function and spelled things the same.

Final words

I know this was a shorter one, but I hope it’s useful. If you want a more in-depth version of this article looking into things like passing pointers and arrays make sure to let me know in the comments section below and on my discord (link in sidebar)!


Liked it? Take a second to support WireWhiz on Patreon!
Become a patron at Patreon!