[SerializeReference] Generic (Inflated) Types

We’re working on a new set of tools and stumbled upon this limitation of the [SerializeReference] attribute. In the documentation (Unity - Scripting API: SerializeReference) it says any managed type can be saved as a reference unless it’s an inflated type. This means that this will work:

interface IAnimal
{ }

class Cat : IAnimal
{
   int health = 9;
}

[SerializeReference]
public IAnimal[] animals = { new Cat() };

However, wrapping the array declaration in a generic class won’t work:

// ...

class Zoo<T> where T : IAnimal
{
    [SerializeReference]
    public T[] animals = { new Cat() }; // incorrectly serialized
}

public Zoo<IAnimal> zoo = new Zoo();

Is this going to be supported? In the foreseeable future at least. Or is there a technical limitation? Just asking in case we can wait or work around this. Thanks!

6 Likes

Reply from the devs: “Supporting inflated types for serialize reference is currently not planned.”

1 Like

Okay, thanks @LeonhardP

Well this is actually a really sad news… I was really looking forward this feature :frowning:

3 Likes

We are so close to be able to use interfaces in Unity! Also - I found out that this is wrong in the docs:

  • Field value cannot be a specific specialization of a generic type(inflated type).

Not only the value, but the actual type of the field must be a non-generic type for serialization to succeed.

This is likely a superficial restriction as it can be worked around by storing a System.object with [SerializedReference], then cast to your interface value. Nevertheless, it is somewhat ugly and it would be great if we can have this implemented.

For the value itself, we can create a factory class that handles the subclassing. Some more boilerplate code, but tolerable.

Again, we are so close to having interfaces work as they should in Unity! Looking forward to the day this lands eventually :slight_smile:

3 Likes

I don’t think this is correct, unless I did not understand what you said there, because I tried to create an object and cast it to a non-generic, but it failed as well. That makes sense, because objects are given by reference, then the underlying generic object remains untouched by the type cast. Other workarounds (to put a non-generic class inside a generic class and extend the generic) also does not work.

What I don’t understand is: why there is such limitation? Isn’t “ExampleClass” as concrete as “ExampleClassInt”? I even tried to get a generic class through Type.GetType and instantiate it with Activator.CreateInstance, and it worked just fine. Does Unity use something else to instantiate the object?

In version 2023 this is already a thing. Finally!

5 Likes

Do you know if this feature will be brought back to Unity 2022?

2 Likes

Doesn’t look like…

I would really like that feature in 2022!

As some said earlier. It seems like it seems like the restriction on the field type (as opposed to the value type) is an artificial limitation, as the type of the field itself would have nothing to do with the deserialization of the object, if that object is of a non generic derived type.

Proper generic support would also be nice. But I am not asking that much

This feature should definitely come in the 2021 and 2022 versions. Please.

1 Like

New features never get back ported.