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!
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
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?
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