Version: Unity 6.5 (6000.5)
Language : English
Native plug-ins
Call functions

Introduction to native plug-ins in Unity

A native plug-inA set of code created outside of Unity that creates functionality in Unity. There are two kinds of plug-ins you can use in Unity: Managed plug-ins (managed .NET assemblies created with tools like Visual Studio) and Native plug-ins (platform-specific native code libraries). More info
See in Glossary
provides a C interface that you can access from managed (C#) scriptsA piece of code that allows you to create your own Components, trigger game events, modify Component properties over time and respond to user input in any way you like. More info
See in Glossary
.

Unity native plug-inA platform-specific native code library that is created outside of Unity for use in Unity. Allows you can access features like OS calls and third-party code libraries that would otherwise not be available to Unity. More info
See in Glossary
support uses the standard .NET Platform invoke feature. This feature lets C# code call unmanaged functions exported by native code libraries. It uses a process called marshalling to transfer data between managed and unmanaged code.

For an example of a native plug-in, check out the Simplest Plug-in example on Github.

Import native plug-ins

You can import native plug-ins into a Unity project in two basic forms:

  • Binary files precompiled for specific platforms and CPU architectures.
  • Source code files, which are compiled as part of your Unity project build process. (To use source code files as a native plug-in, your project must use the IL2CPP scripting backend.)

To work in Unity, a native plug-in must export its external functions using C linkage. This type of linkage avoids C++ name mangling and other Application Binary Interface (ABI) issues.

To access an unmanaged function from managed C# code, you declare a C# static extern function with the same name and compatible return and parameter types, then call it like any other method. Refer to Call functions for the full declaration rules and examples.

Unity supports precompiled static libraries on Apple mobile platforms (iOS, tvOS and visionOS) and on Android. Plug-ins that you import into your Unity project as source code files are also statically linked. Unity supports source code plug-ins in projects that use the IL2CPPA Unity-developed scripting back-end which you can use as an alternative to Mono when building projects for some platforms. More info
See in Glossary
scripting backendA framework that powers scripting in Unity. Unity supports three different scripting backends depending on target platform: Mono, .NET and IL2CPP. Universal Windows Platform, however, supports only two: .NET and IL2CPP. More info
See in Glossary
. Source code plug-ins aren’t supported for Editor scriptsC# source files composed entirely of code that runs in the Unity Editor only and not in the runtime Player build. Keep such scripts in dedicated Editor assemblies either by placing them in a parent folder called Editor or creating an Editor-only assembly definition.
See in Glossary
or when code runs in Play mode.

After you import plug-in files into your Unity project, you must set properties that determine when the library should be loaded. To do this, select the imported files in the Unity Project panel and set the relevant properties in the InspectorA Unity window that displays information about the currently selected GameObject, asset or project settings, allowing you to inspect and edit the values. More info
See in Glossary
. Refer to Change plug-in settings for more information.

Note: When you load a native plug-in during a Unity Editor session – either through an Editor script or in Play mode, the Editor cannot unload it. To update a native plug-in after it has been loaded by the Editor process – either as a precompiled binary or as a source code file, you must restart the Editor application. Otherwise, the Editor continues to use the loaded version of the plug-in instead of the updated version.

Interoperate with a native plug-in

The C# code that you write in Unity is managed by the scripting runtime. The scripting runtime manages where data is stored in memory and routinely moves data around to avoid memory fragmentation. Unmanaged code in a native plug-in, on the other hand, handles its own memory directly and can use pointers to address specific memory locations. When you write managed code that interoperates with unmanaged code, you have to be careful about where the data is stored, when the data is accessed, and which side is responsible for freeing memory that’s no longer needed.

Some data types can be represented in different ways in managed code as compared to native code. .NET provides an interop marshaller that provides a default representation and conversion for most types. For situations where the default behavior is incorrect or suboptimal, the .NET Interop Services API provides the following attributes that you can use to explicitly define the desired representation and conversion for specific data types:

Refer to Pass data between managed and unmanaged code for more information.

Basic plug-in example

A simple, C-language native library with a single function might have code that looks like this:

float ExamplePluginFunction ()
{
    return 5.0F;
}

Note: This minimal example omits the export annotation for brevity. A precompiled dynamic library (such as the one imported below with [DllImport("PluginName")]) must export its functions. Refer to Call unmanaged functions from managed code for the EXPORT_API annotation that exports a function on each platform.

If you compiled this code separately and imported the compiled library into your Unity project, you could use the following C# script to call the ExamplePluginFunction():

using UnityEngine;
using System.Runtime.InteropServices;

class ExampleScript : MonoBehaviour
{
    // Use the library file name for dynamically linked libraries.
    [DllImport ("PluginName")]
    private static extern float ExamplePluginFunction ();

    void Awake ()
    {
        // Calls the ExamplePluginFunction inside the plugin
        // And prints 5 to the console
        Debug.Log (ExamplePluginFunction ());
    }
}

If you import the native code as source code, then you must use __Internal in the DllImport attribute rather than the library name:

using UnityEngine;
using System.Runtime.InteropServices;

class ExampleScript : MonoBehaviour
{
    // Use __Internal instead of the library name for source-code plug-ins.
    [DllImport ("__Internal")]
    private static extern float ExamplePluginFunction ();

    void Awake ()
    {
        // Calls the ExamplePluginFunction inside the plugin
        // And prints 5 to the console
        Debug.Log (ExamplePluginFunction ());
    }
}

Refer to DllImport attribute for more information on how to identify the native plug-in library to load.

Additional resources

Interoperation between managed and unmanaged code is a complex topic. This documentation is only intended to provide a brief orientation to the subject. Refer to the following .NET documentation to gain a more thorough understanding:

Note: This documentation discusses the Platform Invoke interop model. However, you can also use the COM Interop model discussed in Microsoft’s .NET documentation.

Native plug-ins
Call functions