I’ve been encountering a strange problem that goes against my expectation and understanding of script serialization in Unity.
When I define private member variables in my MonoBehaviour or ScriptableObject classes, unless I explicitly attribute them NonSerializable, Unity is holding onto the data during hot reloading (after recompiling scripts).
Consider the following example:
using System;
using UnityEngine;
[ExecuteInEditMode]
public class SerializationTest : MonoBehaviour
{
//[NonSerialized]
private float value = 0f;
private void Awake()
{
Debug.Log($"Awake:{value}");
}
private void OnEnable()
{
Debug.Log($"OnEnable:{value}");
value = UnityEngine.Random.value * 100f;
}
}
By default, I would expect the private member ‘value’ not to be serialized and revert to 0, which is true when the scene is reloaded or entering play mode. However, after script recompilation the value persists and does not reset to 0, unless I specifically attribute it with [NonSerialized].
If you test the code above with NonSerialized commented out, you’ll see in the console that OnEnable is called and still has the previously assigned value, whereas if NonSerialized is uncommented the value is 0 (as is expected).
It seems there is a middle ground where the value is partially serialized (or at least stored by Unity) during script recompilation only. I have also noticed that private members are visible in the Inspector when debug mode is enabled, except if the NonSerialized attribute is applied.
This behavior has caused some bugginess in my code due to objects holding onto old values, leading to a state of partial initialization. The IDE may suggest [NonSerialized] is unnecessary for private members, however what I am experiencing is contrary to that idea and therefore to ensure my private data is fully reset upon reload I must qualify the members with the NonSerialized attribute.
I don’t recall this being the case in earlier versions of Unity, though it may have been something I overlooked. Here is the related docs which as far as I have found doesn’t explain the behavior I am seeing.
Does anyone have any insight into this? For now, my workaround is simply to be very explicit with my attributes in all variable declarations.