Can't override type of SerializeReference fields in prefab instances

I ran into another issue with [SerializeReference]. If I have such a field on a component that’s used in a prefab, and I then change the type inside the that field to something else in a prefab instance (either as part of another prefab, or in the scene itself), the new type doesn’t actually get saved. I think this is because Unity’s serialisation format doesn’t actually have a way to specify type overrides yet.

Is this a known issue? Are there any known workarounds?

With all these teething issues, I’m probably going to go back to [SerializeField], ISerializationCallbackReceiver and type-indicating enums for now. The new feature to serialise references is really powerful, but doesn’t quite feel like a first-class citizen in Unity just yet.

Not a known issue AFAIK. Could you please submit a bug report?

Sorry, took me a few days to make a separate Unity project for this, but I’ve submitted a bug report now (case 1199395).

1 Like

It’s now on the public issue tracker: Unity Issue Tracker - Cannot override type of [SerializedReference] fields in prefab instances

1 Like

@LeonhardP can you say if there are any plans to include a default property renderer for [SerializedReference] fields? (I’m imagining something that just gives you a dropdown for all types derived from field’s type and then just uses the normal property rendering for the actual value.)

Thanks for the bug report! I’ve relayed your question to the devs.

1 Like

Got two replies from the devs.

Re: default property renderer, there are no plans at the moment.

Re: overriding type in a prefab instance,
unfortunately this isn’t possible due to how prefab instances store modifications (path/value). It’s a known limitation but is currently undocumented. We’ll include a note in the docs.

Thanks for the quick response. That’s unfortunate. The lack of a default renderer isn’t a huge issue, since it’s not too hard to write one yourself, but not being able to actually change the type of a field is a pretty big deal breaker for a feature that’s supposed to enable polymorphic serialisation.

1 Like

Prefab variant fields are resetted too from my testing.
Do that limitation applies to prefab variants?

I’m pretty sure it does, since it’s just a fundamental limitation of Unity’s current serialisation format.

1 Like

This is my setup:
The interface and the implementation:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public interface IBullet
{
    void Fire();
}

public class MachineGunBullet : IBullet
{
    [SerializeField] string aName = "MachineGun bullet";
    void IBullet.Fire()
    {
       
    }
}

public class AK47Bullet : IBullet
{
    [SerializeField] string aName = "AK47 bullet";
    [SerializeField] GameObject particle;
    void IBullet.Fire()
    {
       
    }
}

public class ShotGunBullet : IBullet
{
    [SerializeField] string aName = "ShotGun bullet";
    [SerializeField] AudioClip shotSound;
    void IBullet.Fire()
    {
       
    }
}

And the component:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Shooter : MonoBehaviour
{
    [SerializeReference] [SerializeReferenceButton] IBullet mainBullet;
    [SerializeReference] [SerializeReferenceButton] List<IBullet> bullets;
    // Start is called before the first frame update
    void Start()
    {
       
    }

    // Update is called once per frame
    void Update()
    {
       
    }
}

The ‘[SerializeReferenceButton]’ comes from a plugin developed by @TextusGames . Basically it creates a button beside the field which lets you to create and add an implementation of the interface from a dropdown list of all available implementation.

The shooter is attached to a gameobject which is a prefab. The default implementation of ‘mainBullet’ in shooter is ‘ShotGunBullet’. If I drag the prefab into scene and modify ‘mainBullet’ to ‘AK47Bullet’ from ‘ShotGunBullet’, I am able to do so. Then if I press play and enter playmode, the field ‘mainBullet’'s data does not get lost or revert into something. Even I can drag the prefab into another prefab and yet no data loss. Is the issue fixed? I am confused.

Unity version 2020.3 Mac for iOS platform.