With Unity 5, there is no difference in terms of engine features between Personal/Free and Professional editions. This means that "Native Code Plugin Support" is not a problem anymore and there are no restrictions with DLLs and C++(unmanaged) code.
This guide really only applies to Unity 4 and below
When dealing with unmanaged and managed code, verbiage like P/Invoke, marshaling, interoperability get thrown around. The whole ordeal can be a bit daunting.
This guide will go over dealing with DLLs in Unity Free/Standard and Unity Pro. Even with the native(unmanaged) code barrier in Unity Free, it is still possible to use unmanaged code.
Specifically, we will be making a C# managed DLL which relies on/references a C++ unmanaged DLL and then use those functions in Unity.
TLDR; For Unity 4 Pro and Unity 5:
UnityProject
->Plugins
TLDR; For Unity Free:
UnityProject
UnityProject
->Plugins
BuildRoot
->Data
->Plugins
To start, lets create the unmanaged DLL which the other pieces rely on.
Visual C++
->Win32
->Win32 Console Application
TestCPPLibrary
Application Type
to DLL
Empty Project
box on the same pageTestCPPLibrary.h
// TestCPPLibrary.h
#ifdef TESTFUNCDLL_EXPORT
#define TESTFUNCDLL_API __declspec(dllexport)
#else
#define TESTFUNCDLL_API __declspec(dllimport)
#endif
extern "C" {
TESTFUNCDLL_API float TestMultiply(float a, float b);
TESTFUNCDLL_API float TestDivide(float a, float b);
}
TestCPPLibrary.cpp
// TestCPPLibrary.cpp : Defines the exported functions for the DLL application.
//
#include "TestCPPLibrary.h"
extern "C" {
float TestMultiply(float a, float b)
{
return a * b;
}
float TestDivide(float a, float b)
{
if (b == 0) {
return 0;
//throw invalid_argument("b cannot be zero!");
}
return a / b;
}
}
Visual C#
->Windows
->Class Library
TestCSharpLibrary
Add
->Existing Item
TestCPPLibrary
project.Properties
Application
tab, change the Target Framework
to .NET Framework 3.5
using System;
using System.Runtime.InteropServices;
namespace TestCSharpLibrary
{
public class TestCSharpLibrary
{
// From c++ Dll (unmanaged)
[DllImport("TestCPPLibrary")]
public static extern float TestMultiply(float a, float b);
// From c++ Dll (unmanaged)
[DllImport("TestCPPLibrary")]
public static extern float TestDivide(float a, float b);
public static float SharpMultiply(float a, float b) {
return (a * b);
}
public static float SharpDivide(float a, float b) {
if (b == 0)
{
return 0;
}
return (a / b);
}
}
}
Right click the solution and press Build
(F7). It should run until you see:
========== Build: 2 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
You should be able to find both DLLs in the C# project folder:
TestCSharpDll\TestCSharpLibrary\Debug\TestCPPLibrary.dll
TestCSharpDll\TestCSharpLibrary\TestCSharpLibrary\bin\Debug\TestCSharpLibrary.dll
Since native(unmanaged, the c++ DLL in our case) is a Pro/Mobile-only feature, it is quite easy to get this running in Unity Pro, but a bit more involved for Unity Free/Standard/Indie.
If you are using Unity Pro,
TestCSharpLibrary.dll
, TestCPPLibrary.dll
) into UnityProject
->Plugins
The project will work in the Unity Editor and when you make a Build
If you are using the standard version of Unity:
TestCSharpLibrary.dll
, the C# managed DLL, into UnityProject
->Plugins
TestCPPLibrary.dll
, the C++ unmanaged DLL, into the UnityProject
root.This will allow the project to run in the Unity Editor but will not work in a build.
To get your project working in a build... After you build your project:
TestCPPLibrary.dll
, into your Build Root
->Data
->Plugins
, alongside your other DLLHere is a simple script utilizing the DLLs:
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
using System.IO;
public class UseDll : MonoBehaviour {
// Straight From the c++ Dll (unmanaged)
[DllImport("TestCPPLibrary", EntryPoint="TestDivide")]
public static extern float StraightFromDllTestDivide(float a, float b);
// Use this for initialization
void Start () {
/* */
// Call the C# DLL SharpMultiply function
float multiplyResult = TestCSharpLibrary.TestCSharpLibrary.SharpMultiply(3, 5);
// Call the C# DLL TestDivide function which relies on the C++ DLL for this functionality
float divideResult = TestCSharpLibrary.TestCSharpLibrary.TestDivide(15, 3);
float straightFromDllDivideResult = StraightFromDllTestDivide(20, 5);
// Print it out to the console
Debug.Log(multiplyResult);
Debug.Log(divideResult);
Debug.Log(straightFromDllDivideResult);
// Write the result into a file, so we can even see it working in a build
using(StreamWriter writer = new StreamWriter("debug.txt", true))
{
writer.WriteLine(multiplyResult);
writer.WriteLine(divideResult);
writer.WriteLine(straightFromDllDivideResult);
}
/* */
}
// Update is called once per frame
void Update () {
}
}
Running the script, should output to the console and write to debug.txt:
System.Reflection.ReflectionTypeLoadException
If you are getting an error similar to Internal compiler error. System.Reflection.ReflectionTypeLoadException
in Unity when trying to build your project; You need to change the targeted .NET version of your C# file to something like .NET 3.5.
Properties
Application
tab, change the Target Framework
to .NET Framework 3.5
If you are getting this error, you probably need to recompile your libraries for x64 platform (64 bit).
In Visual Studio, go to the properties of your project, then at the top click the "Configuration Manager..." button. In the table, under the Platform
column, change it to "x64" then recompile your project.