Summary
Cloning a ScriptableObject at runtime via Object.Instantiate() corrupts a List<T> [SerializeReference] field in a built Standalone Player (not in the Editor).
The corruption occurs if and only if another (non-list) [SerializeReference] field is declared before the list field on the same class. Swapping the two fields' order avoids it entirely.
Repro
See attached NUnit Playmode test suite.
Step to reproduce
[Serializable] public abstract class Base { }
[Serializable] public class ItemA : Base { }
[Serializable] public class ItemB : Base { }
[Serializable]
public class Host
{
[SerializeReference] public Base OtherReference; [SerializeReference] public List<Base> Items = new();
}
public class HostAsset : ScriptableObject
{
[SerializeReference] public Host Data;
}
var asset = ScriptableObject.CreateInstance<HostAsset>();
asset.Data = new Host();
asset.Data.Items.Add(new ItemA());
asset.Data.Items.Add(new ItemB());
var clone = Object.Instantiate(asset);
Actual results:
(Player build only): clone.Data.Items == [OtherReference's value (or null), ItemA] ItemB is lost.
Expected results:
clone.Data.Items == [ItemA, ItemB]
Reproducible with versions:
6000.6.0b6, 6000.6.0f1
Not reproducible with versions:
6000.6.0b5, 6000.7.0a6
Can’t test with versions:
NA
Tested on (OS):
WinPlayer
Note
Found from com.unity.behavior: https://discussions.unity.com/t/behavior-package-1-0-16-released/1721488/15
This is breaking all Behavior graphs in player build after 6000.6.0b5.
A fix is available in 6000.7.0a6