Unity SerializeReferenceExtensions: a type picker for Unity's [SerializeReference] fields
Provide popup to specify the type of the field serialized by the [SerializeReference] attribute in the inspector.
At a glance
- What is it?
- SerializeReferenceExtensions is an MIT-licensed C# library that adds a `SubclassSelector` dropdown to Unity fields marked `[SerializeReference]`, so an interface-typed field can be assigned a concrete type from the inspector. The judgement is that the eligibility rules are the real product, because they are where Unity's own serialization limits and the library's own decisions meet.
- Who is it for?
- SerializeReferenceExtensions fits a Unity team that uses `[SerializeReference]` for polymorphic data and has grown tired of the built-in type picker, and that wants fuzzy search, collection support and the ability to restore field values when the type changes. It does not fit a project that just needs a plain serializable field, and it does not fit a team on a Unity version older than 2021.3 LTS, which the project does not officially support.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly C#, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Unity's [SerializeReference] has no type picker worth using
SerializeReferenceExtensions is a Unity library whose whole purpose is to improve one specific part of the Unity editor.
Unity's `[SerializeReference]` attribute is how you serialize a field whose type is an interface or an abstract class, storing the concrete type alongside the value so the right subclass is reconstructed on load. It is the mechanism for polymorphic data in the inspector, and it is how a single component can hold a command, a behaviour or a configuration object chosen at author time.
The problem the library addresses is the interface for choosing which concrete type goes in. Unity's own tooling for this is limited, and this project replaces it with an inspector dropdown called `SubclassSelector`. The idea is small and the consequences are not, because the field is typed as an interface and the editor has to search the loaded assemblies for types that could satisfy it.
The key features list makes the scope clear. Select a concrete type for `[SerializeReference]` fields via dropdown. Search candidates with a fuzzy finder. Collection support, meaning `T[]`, `List<T>` and similar. Nested type support. Customise the type display name and path with `[AddTypeMenu]`. Support `CustomPropertyDrawer` for selected subtypes. When switching types, restore previous values by matching property names, which is JSON-based. And context menu utilities to copy and paste managed-reference values and to clear or reset them.
There is also a Unity-version-specific feature. On Unity 2023.2 and later, the library supports variance matching, the `in` and `out` modifiers, for generic interfaces, so a field typed `ICommand<int>` can offer candidates that implement it covariantly or contravariantly.
The licence is MIT, with a `LICENSE` file at the repository root.
The eligibility table is where the real decisions live
The documentation has a section on type discovery and eligibility rules, and it is the part of the documentation worth reading twice, because it is where the library's decisions and Unity's own limitations meet.
The dropdown is built in two steps. First it enumerates candidate types, then it filters by eligibility under intrinsic rules and by compatibility with the field's base type.
The intrinsic rules are eight. A top-level `public` type is eligible, and internal or non-public top-level types are not listed. A nested `private` type is eligible, which the documentation notes is useful for encapsulated implementations. A nested `public` type is eligible and listed like other candidates. An `abstract` type is not eligible, because it cannot be instantiated. A generic type, open or constructed, is not eligible, with the note that base type generics are supported but generic candidate types are excluded. A type deriving from `UnityEngine.Object` is not eligible, and this is labelled a Unity `SerializeReference` limitation. A type with `[Serializable]` applied is eligible, since Unity's `SerializeReference` requires serializable types. And a type with `[HideInTypeMenu]` applied is not eligible, because it is explicitly hidden from the menu.
Two of those rules are worth pausing on. The `UnityEngine.Object` exclusion is a hard Unity limitation, not a choice, which means a `[SerializeReference]` field can never hold a MonoBehaviour or a ScriptableObject, whatever the library does. And the generic candidate exclusion means the library will not offer you a generic implementation to assign, which removes a whole class of designs from consideration and is the reason the generic support section is scoped to generic base types rather than generic concrete types.
The nested `private` eligibility is the opposite story. Supporting them lets you keep a polymorphic implementation private to the type that declares it, which is a meaningful design constraint removed.
Installing it three ways, and the version floor
The requirements come first, and they are the constraint to check before anything else.
Unity 2021.3 LTS or later is officially supported. Unity 2023.2 or later is recommended when you use generic field types, and the documentation points at a Unity blog post on `SerializeReference` improvements in Unity 2021 LTS for the reason older versions are limited.
For installation there are three routes.
You can download any version from the releases page and install the `.unitypackage`.
You can install via git URL in the Package Manager, choosing Add package from git URL and entering:
https://github.com/mackysoft/Unity-SerializeReferenceExtensions.git?path=Assets/MackySoft/MackySoft.SerializeReferenceExtensionsTo pin a version, append `#{VERSION}`, so for the current release the URL ends with `#1.7.0`.
Or you can install it from the Open UPM registry, which the documentation lists as `com.mackysoft.serializereference-extensions` and the registry page as `openupm.com/packages/com.mackysoft.serializereference-extensions/`.
openupm add com.mackysoft.serializereference-extensionsThe git URL route with the `?path=` parameter is the interesting one, because it points the Package Manager at a subdirectory of the repository rather than the whole thing. That is what lets the same repository hold the package, the example project and the test project, and it is why the pinned version goes in the URL fragment rather than in a separate field.
The repository layout reflects that arrangement, with `Assets/`, `Packages/` and `ProjectSettings/` at the root alongside `AGENTS.md` and `STATUS.md`, so the project is a full Unity project that also contains the package.
Using the attribute, and what the example demonstrates
The usage example in the documentation is a complete, self-contained class, and it demonstrates several of the features at once rather than just the basic case.
The core is one attribute on an interface-typed field:
[SerializeReference, SubclassSelector]
ICommand m_Command;The comment on that line says it plainly: the type that implements ICommand will be displayed in the popup. The `SubclassSelector` attribute is what the library reads, and `SerializeReference` is what tells Unity to store the concrete type with the value.
Collections are handled the same way, with `ICommand[]` initialised to `Array.Empty<ICommand>()`, and the example's `Start` method invokes each command with a null-conditional call.
Nested types are supported, and the example declares a `NestedCommand` class inside `Example` marked `[Serializable]`. That matters because the eligibility rules allow nested private types, and the example shows a nested public one.
The example also includes a `StructCommand`, declared as a `public struct`, which is the interesting edge case: a value type implementing an interface, stored through a reference-typed field.
And the menu override is shown with `[AddTypeMenu("Example/Add Type Menu Command")]` on `AddTypeMenuCommand`, which is how you control the path a type appears under in the dropdown rather than accepting the namespace-derived default.
Two more example types round it out. `DebugCommand` holds a serialised string and logs it, and `InstantiateCommand` holds a serialised `GameObject` and instantiates it at the origin with `Vector3.zero` and `Quaternion.identity`.
Copy and paste that survives a script reload, with two different semantics
The context menu utilities are more carefully specified than the rest of the documentation, and the detail is because the two commands do genuinely different things.
Right-click a managed-reference field or an individual collection element and choose Copy. The copied snapshot remains available across script reloads during the current Editor session. To preserve unresolved reference data, copying null fields is disabled on objects that contain missing managed-reference types.
Paste Values Only copies matching serialized fields into the existing destination instance. It preserves the destination type and reference identity, and keeps destination fields absent from the copied data. Both the copied value and the destination must be non-null.
Paste Type and Values creates an independent instance of the copied type when that type is assignable to the destination field. It also works with an empty destination. Copying a null reference and using this command clears the destination.
The distinction is the important part. Values Only is a merge into the existing object, which keeps whatever the destination had for fields the copy does not mention, and keeps the destination's identity so that other things still pointing at it stay valid. Type and Values replaces the object with a new instance of the copied type, which is how you change the type of a field and bring the old values along.
The scoping rules are stated too. Copy and paste operate on one selected object at a time, and the commands are disabled when multiple objects are selected. They apply to a single managed-reference property, including a nested field or a collection element. Copying a whole regular `[SerializeField]` parent, or an entire collection, is outside what these commands do.
Switching types restores values by matching property names
The one feature in the list that changes the workflow rather than adding to it is value restoration on type switch, and the implementation detail is specified: it is JSON-based, and it works by matching property names.
When you change the concrete type of a `[SerializeReference]` field in the inspector, the naive behaviour is to lose the values. The library instead attempts to carry them over, matching the properties of the old type against the properties of the new one by name.
That is a reasonable heuristic and it has a clear limit. It is name-based, not type-based, so it will carry a value across if the new type happens to have a field of the same name, and it will not carry anything across if the new type renamed the field or the value needs conversion. The documentation describes the mechanism without claiming more than that.
The generic support section is a separate improvement on the same theme. Unity 2023.2 and later supports generic type instances for `SerializeReference` fields more reliably, and the library enhances type discovery for generic base types on top of that.
The two documented patterns are a generic interface as the base type, where the field is declared as `ICommand<int>` and the candidates shown are those that implement `ICommand<int>`, including the variance rules where applicable. And an abstract generic base type, where the field is `BaseCommand<int>` and the candidates are those derived from `BaseCommand<int>`.
The documentation adds a note that matters: the candidate types shown in the menu still follow the eligibility rules above. So the generic support widens the set of base types you can declare, it does not relax the constraints on which concrete types can be offered.
Editorial conclusion
SerializeReferenceExtensions fits a Unity team that uses `[SerializeReference]` for polymorphic data and has grown tired of the built-in type picker, and that wants fuzzy search, collection support and the ability to restore field values when the type changes. It does not fit a project that just needs a plain serializable field, and it does not fit a team on a Unity version older than 2021.3 LTS, which the project does not officially support. Verify first that the base type of your field is one the library's compatibility rules accept, that every concrete type you want to offer is marked `[Serializable]` and is a top-level public type or a nested type, and that the Unity version in your project is 2021.3 or later, with 2023.2 or later if you use generic field types.
Frequently asked questions
What does Unity SerializeReferenceExtensions add to the Unity editor?
It provides an Inspector dropdown, the `SubclassSelector` attribute, for fields serialized by Unity's `[SerializeReference]`, so you can pick the concrete type from a list of eligible implementations. It also adds fuzzy search, collection support, nested type support, `[AddTypeMenu]` naming, value restoration on type switch, and copy and paste context menu commands.
Which Unity versions does SerializeReferenceExtensions support?
Unity 2021.3 LTS or later is officially supported. Unity 2023.2 or later is recommended when you use generic field types, because that is where Unity's own support for generic `SerializeReference` instances became more reliable.
How do I install SerializeReferenceExtensions in a Unity project?
Three routes are documented. Install the `.unitypackage` from the releases page, add the git URL in the Package Manager with `?path=Assets/MackySoft/MackySoft.SerializeReferenceExtensions` and optionally a `#VERSION` fragment to pin, or install from the Open UPM registry with `openupm add com.mackysoft.serializereference-extensions`.
Why does my type not appear in the SubclassSelector dropdown?
The intrinsic eligibility rules exclude several cases. Internal or non-public top-level types are not listed, abstract types cannot be instantiated, generic candidate types are excluded, types deriving from `UnityEngine.Object` are excluded by a Unity `SerializeReference` limitation, and types with `[HideInTypeMenu]` are hidden. A type also needs `[Serializable]` to be eligible at all.
What is the difference between Paste Values Only and Paste Type and Values?
Paste Values Only copies matching serialized fields into the existing destination instance, preserving its type and reference identity and keeping fields the copy does not mention. Paste Type and Values creates an independent instance of the copied type when it is assignable to the destination field, works with an empty destination, and clears the destination if you copy a null reference.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/mackysoft-unity-serializereferenceextensions)Was this useful?