Native Plugin - How to create asset for C++

I’m developing a native plugin in Unity. I need to create assets whose instance memory is not in C#, but in a model managed by my C++ DLL. As the asset’s data can get heavy (10+ Mb), I can’t rely on duplicating it (a version in C# and another in C++).

The asset in itself just exposes getters/setters calling DllImport methods to get/set the C++'s model memory.

I need to create a custom Inspector for these assets to allow users to edit them, just like a ScriptableObject would allow for.

I also need to serialize and deserialize these assets into binary, to save them in Unity and be able to use them in-game.

I looked for references of native plugins online but I didn’t find any packages that create assets not for Unity but for the native plugin. I wonder if it’s not better to avoid using ScriptableObjects, and make fully custom assets (like .json files) and create custom editor windows to edit them.

What is the common pipeline to create assets referencing native plugin models ?

That is too unspecific. You are figuratively asking about how to create a “file of unknown type and purpose” whose memory is to be managed by a native plugin.

So tell us a little more about this “asset” and also the reason why its memory has to be managed by a C++ plugin, as opposed to using a NativeArray<byte> for instance. Also which platforms this plugin needs to be compatible with, as well as which frameworks/libraries this plugin will utilize since they all need to be compatible with a) Unity and b) each target platform.

For binary serialization, use the serialization package. This works well together with native collections. To make your asset interoperate with the editor, you have to write a ScriptedImporter.

Thanks for the info, I’ll try to explain myself with an example.

Let’s say I want to create a native plugin to generate an image in the editor, and load the generated image in the plugin in the player build.

  • The image generator needs an asset to set the parameters to generate the image (e.g. the background color, the image title, etc.). Let’s call this asset GeneratorSettings.
  • In the editor, I want to create a “Create” button that given an asset, pass the asset data to the native plugin, the plugin generates an image and returns the image data to the editor which saves it.
  • Finally, in the player build, a MonoBehaviour script loads the image and pass the data to the native plugin which performs some operation.

Actually, rather than creating custom assets, maybe it’s preferrable to create a ScriptableObject to edit the GeneratorSettings in the editor, and create dll methods to copy/marshal the asset data to the C++ native plugin. However, for the generated image, as it can be quite big, should I do the same and copy the data from C++ to C# so that the generated image is saved using Unity Serialization API?

Though, this setup leads to have duplicated data at some point in C# and C++: when I hit the create button, the asset data is copied over from C# to C++ and if I edit it in the editor, the changes are not necessarily reflected in C++.

If you want data to be accessible in the editor and usable by C++, you will need to “duplicate” it. I put “duplicate” in quotes because you won’t actually have duplicate data; rather, you’ll have separate representations of the data, which may differ between C++ and C# for certain types.

Since you haven’t specified exactly what you’re trying to achieve, we’re making an educated guess here. However, for any data to be exposed in the editor, it must exist in C# unless you implement a custom serialization with Unity’s serialization package. The C++ side won’t be able to use it directly for two main reasons:

  1. Some (or all) of your data may not be blittable, though we can’t determine this without more details.
  2. Data in C#'s managed memory space cannot be reliably accessed by C++ because it isn’t stored at a fixed memory location. The garbage collector moves it for various reasons, making direct access unpredictable. To work around this, you would either need to pin the data, which is cumbersome and too much work for a plugin or, more reliably, copy it into an equivalent C++ representation and work with that.

I don’t think you will have the same problem with native collections for the second point, if you use Unity’s serialization package to implement a custom serialization, but you still need to consider transformations and a duplicate representation for any data that is not blittable.

Also for data that big, you don’t want to serialize/deserialize automatically but on demand for performance reasons and take into account any data, (usually arrays) that can get bigger than 85K and moved on the large object heap.

My KurtMaster2D games do this: Unity wraps them all, they’re all native C / C++, and Unity preps a Texture2D, pins it in GC memory, passes the pointer to native code, and then the native code blasts the current frame of my game into the texture and returns.

Now Unity marshals that texture back into its own managed code and presents it for the user… lather rinse repeat for next frame.

Here’s some notes on how:

Pinning a texture for manipulation via native code:

KurtMaster2D:

Apple iTunes: ‎KurtMaster2D on the App Store

Google Play (including TV): https://play.google.com/store/apps/details?id=com.plbm.plbm1

1 Like

Thanks for your feedbacks, it helped me design the architecture for the plugin.

I want indeed to pass non blittable types. So instead of trying to pass the entire complex classes, I created multiple simpler methods that pass either basic typed variables or native collections.

The plugin only needs to load the data once, so the easier solution seemed to create “regular” scriptable objects in Unity and add interop methods to pass these assets to C++ using blittable types or native collections. The plugin doesn’t need to support hot reload so it doesn’t matter that a change on the scriptable object should be reflected in the plugin at runtime.

1 Like