I’ve stumbled into this issue, using unity 2023.1.0b20.
If I add a new serializable field (public enum) to a component which is already used in a prefab and then change the value of that field on an instance of that prefab, then I’d expect Unity to create an override for it.
But it doesn’t. And what’s worse…
Unity also resets the value of the field during deserialization. However, if I break the connection to the prefab, then everything works as expected and the new field is serialized normally.
Kinda somewhat expected as, even when you add new serialised fields to objects, the data isn’t immediately serialised into said assets. The data only gets added to the object’s yaml when it’s been dirtied and then saved, or force-re-serialised (more on that later). The objects will still have a default value for this new field, of course, it’s just not written to disk yet.
Prefabs work by keeping track of a list of modifications. If the data doesn’t exist in the prefab then it can’t considered an override as there’s no underlying data to compare to.
I made a little editor window once to let me re-serialise directories to ensure that - when I add/remove serialised members - I can update all the objects in question as well.
Hi, this makes a lot of sense. Thank you a lot for your explanation, @spiney199 !
I experimented a bit and if I dirty the prefab instance, then the new field persists on that instance. New instances of the prefab, however, seem to not serialize the new fields, unless I dirty one of their existing (old) fields.
Now I wanted the new fields to be serialized as part of the prefab, so I disconnected the instances and deleted the prefab, recreated it from one of the former instances (after dirtying it, just to be sure) and reconnected the other instances, but still, the behavior (new fields not recognized) does not change for new instances of that prefab, even though I’ve recreated it.
It’s like the previous prefabs data is taken out of a cache or something - and I guess forcing re-serialization would fix that? I still have to try that.
Good stuff Spiney, well put about the “list of modifications.”
Here’s my scribbles about how things load / overwrite:
Serialized / public fields in Unity are initialized as a cascade of possible values, each subsequent value (if present) overwriting the previous value:
what the class constructor makes (either default(T) or else field initializers, eg “what’s in your code”)
what may be saved with the prefab
what may be saved with the prefab override(s)/variant(s)
what may be saved in the scene and not applied to the prefab
what may be changed in the scene and not yet saved to disk
what may be changed in OnEnable(), Awake(), Start(), or even later
Make sure you only initialize things at ONE of the above levels, or if necessary, at levels that you specifically understand in your use case. Otherwise errors will seem very mysterious.