Unity_Serilize_reference

How to Serialize an interface in Unity?

So, you’ve fallen in love with interfaces in C# (who wouldn’t?), but Unity’s serialization system has been giving you headaches. You’re not alone! Serializing interfaces in Unity is tricky because the engine’s default serializer doesn’t handle them well. But don’t worry, there are clever workarounds and tools to make it happen with paid and free plugins. Let’s dive into a few approaches, from native solutions to powerful third-party tools like Odin Serializer and some interesting Github repositories.


Why Interfaces are a Serialization Challenge

First, let’s understand the problem. Unity’s serialization system relies on knowing the concrete type of a field to decide whether to serialize it by value (like integers or structs) or by reference (like UnityEngine.Object assets). Interfaces, however, are abstract, they don’t specify a concrete type. This confuses Unity’s inspector and serializer, leading to fields that don’t show up or behave unexpectedly

Unity did introduce [SerializeReference] in 2019.3, which allows polymorphic serialization of non-UnityEngine.Object types (ref link). But even this attribute doesn’t fully solve interface serialization for UnityEngine.Object-derived types (like ScriptableObjects or MonoBehaviours) because it serializes by value, not by reference. So, if you’re trying to serialize an interface that could be implemented by a ScriptableObject, you’ll hit a wall.

Approach 1: Unity’s SerializeReference Attribute

Unity’s [SerializeReference] attribute is a step forward. It lets you serialize polymorphic objects, including interfaces, as long as they’re not derived from UnityEngine.Object. Here’s how it works:

[SerializeReference] 
private ICharacterData characterData;

This field can now hold any serializable class implementing ICharacterData. For example:

[Serializable]
public class WarriorData : ICharacterData 
{ 
    public int strength; 
}

This seems to be the solution of your problem right now but there is a catch: The implementing classes must be marked [Serializable], and they can’t be Unity-specific types like ScriptableObject. This approach is great for pure C# objects but doesn’t help if you need to reference assets or components.

Approach 2: Amazing repositories from the community

This GitHub repository (ref Link) by the user MackieSoft adds a handy [SubclassSelector] attribute that works alongside [SerializeReference] to provide a dropdown menu of implementable types in the inspector. It makes polymorphism more user-friendly .

Remember to follow and star this repository to support the developer.

How to Use It:

  1. Install the package from GitHub.
  2. Decorate your interface field with both attributes:
[SerializeReference, SubclassSelector] 
private ICommand command;

  1. In the inspector, you’ll see a dropdown listing all serializable classes implementing ICommand.

This tool is perfect for cases where you want to assign different implementations of an interface directly in the inspector without writing custom editors. However, it still doesn’t support UnityEngine.Object-derived types.

Approach 3: Odin Serializer and Odin Inspector

Odin is a powerhouse for Unity developers. Its serializer handles interfaces effortlessly, even for UnityEngine.Object types. Here’s how to use it:

Step 1: Install Odin Serializer
You can download it as a .unitypackage or fork the repository for custom builds .

Step 2: Inherit from Serialized Classes
Instead of deriving from MonoBehaviour or ScriptableObject, use Odin’s base classes:

public class YourClass : SerializedMonoBehaviour 
{
    public IYourInterface interfaceField;
}

Now, interfaceField will serialize any UnityEngine.Object implementing IYourInterface, and Odin will display it in the inspector with full reference support. The catch? it’s a paid asset in the unity asset store and cost $55 bucks, we can agree that it’s not cheap at all.

If you need more than just interface serialization and do you want to use all the other facilities provided by Odin, like building custom inspectors with no effort, then you can consider buying a seat.

Approach 4: The Workaround – UnityEngine.Object Fields with Casting

Sometimes, simplicity wins. You can use a UnityEngine.Object field and restrict it to types implementing your interface via a custom property drawer. For example:

[SerializeField] 
private UnityEngine.Object _objectField;

public IYourInterface InterfaceField => _objectField as IYourInterface;

Then, create a custom drawer to validate assignments. It’s not as elegant, but it works without external tools.

Which Approach Should You Choose?

  • For Pure C# Objects: Use [SerializeReference] with mackysoft’s dropdown for a native-friendly solution.
  • For Unity-Specific Types (Assets, Components): Odin Serializer is your best bet. It handles interfaces seamlessly and integrates with Unity’s object system.
  • For Minimal Dependencies: The UnityEngine.Object workaround is clunky but effective.

Remember, serialization is about persistence—ensure your implementation handles edge cases like null references and type changes.

Feel free to share your own experiences or questions in the comments below. Let’s keep the conversation going!


I don’t run ads in this blog, if this was useful to you please consider buy me a coffee.

Help me to reach my goals

If you like the content please consider a donation