Introduction to native plug-ins in Unity
Understand how native plug-ins use platform invoke and marshalling to let your C# scripts call functions in C and C++ libraries.
読み終わるまでの所要時間 4 分最終更新 5日前
A native plug-in is a library of unmanaged code that provides a C interface you can access from managed C# scripts.
Unity native plug-in support uses the standard .NET platform invoke (Microsoft) feature. This feature lets C# code call unmanaged functions that native code libraries export. It uses a process called marshalling (Microsoft) to transfer data between managed and unmanaged code.
For an example of a native plug-in, refer to SimplestPluginExample (Unity Technologies on GitHub).
Native plug-in forms
You can import native plug-ins into a Unity project in the following forms:
- Binary files precompiled for specific platforms and CPU architectures.
- Source code files, which Unity compiles as part of your project build process.
Unity supports precompiled static libraries on Android, Apple mobile platforms (iOS, tvOS, and visionOS), and the Web platform. Desktop platforms don't support precompiled static libraries.
Unity statically links plug-ins that you import as source code files. Unity supports source code plug-ins only in projects that use the IL2CPP scripting backend. Source code plug-ins don't work in Editor scripts or in Play mode.
After you import plug-in files into your Unity project, set the properties that determine which platforms the plug-in is compatible with and when the library loads. To do this, select the imported files in the Project window and set the relevant properties in the window. For more information, refer to Change plug-in settings.
Inspector
?
Function exports and declarations
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, declare a C# function with the same name and compatible return and parameter types, then call it like any other method. For the full declaration rules and examples, refer to Call functions.
static externInteroperation with a native plug-in
The scripting runtime manages the C# code that you write in Unity. 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 handles its own memory directly and can use pointers to address specific memory locations. When you write managed code that interoperates with unmanaged code, 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.
Managed code and native code can represent some data types in different ways. .NET provides an interop marshaller that provides a default representation and conversion for most types. When the default behavior is incorrect or suboptimal, use the following attributes from the .NET Interop Services API to define the representation and conversion of specific data types:
- (Microsoft)
StructLayoutAttribute - (Microsoft)
MarshalAsAttribute - (Microsoft)
FieldOffsetAttribute
For more information, refer to Pass data between managed and unmanaged code introduction.
Interoperation between managed and unmanaged code is a complex topic. For a more thorough explanation, refer to the following .NET documentation:
- Interop marshalling (Microsoft)
- Default marshalling behavior (Microsoft)
- Marshalling data with platform invoke (Microsoft)
Call a function in a native plug-in
A simple C native library with a single function might contain the following code:
float ExamplePluginFunction(){ return 5.0F;}
If you compile this code separately and import the compiled library into your Unity project, you can use the following C# script to call :
ExamplePluginFunctionusing 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() { // Call ExamplePluginFunction inside the plug-in. Debug.Log(ExamplePluginFunction()); // The Console window displays 5. }}
If you import the native code as source code, use in the attribute instead of the library name:
__InternalDllImportusing 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() { // Call ExamplePluginFunction inside the plug-in. Debug.Log(ExamplePluginFunction()); // The Console window displays 5. }}
For more information on how to identify the native plug-in library to load, refer to DllImport attribute.