I tested it, and the results were mostly the same as @SisusCo’s comment.
TestSerializeObject.cs
using UnityEngine;
[System.Serializable]
public class TestSerializeObject
{
public int i0;
public int i1;
public int i2;
public int i3;
public int i4;
public int i5;
}
SerializeFieldBehaviour.cs
using UnityEngine;
public class SerializeFieldBehaviour : MonoBehaviour
{
[SerializeField] TestSerializeObject o0;
[SerializeField] TestSerializeObject o1;
[SerializeField] TestSerializeObject o2;
[SerializeField] TestSerializeObject o3;
[SerializeField] TestSerializeObject o4;
[SerializeField] TestSerializeObject o5;
#if UNITY_EDITOR
// Call this method when creating a prefab in the editor to initialize the values.
[UnityEditor.MenuItem("CONTEXT/SerializeFieldBehaviour/Initialize SerializeField")]
static void InitializeSerializeField(UnityEditor.MenuCommand command)
{
var behaviour = command.context as SerializeFieldBehaviour;
Debug.Assert(behaviour != null);
behaviour.o0 = new() { i0 = 0, i1 = 1, i2 = 2, i3 = 3, i4 = 4, i5 = 5 };
behaviour.o1 = new() { i0 = 0, i1 = 1, i2 = 2, i3 = 3, i4 = 4, i5 = 5 };
behaviour.o2 = new() { i0 = 0, i1 = 1, i2 = 2, i3 = 3, i4 = 4, i5 = 5 };
behaviour.o3 = new() { i0 = 0, i1 = 1, i2 = 2, i3 = 3, i4 = 4, i5 = 5 };
behaviour.o4 = new() { i0 = 0, i1 = 1, i2 = 2, i3 = 3, i4 = 4, i5 = 5 };
behaviour.o5 = new() { i0 = 0, i1 = 1, i2 = 2, i3 = 3, i4 = 4, i5 = 5 };
UnityEditor.EditorUtility.SetDirty(behaviour);
}
#endif
}
SerializeReferenceBehaviour.cs
using UnityEngine;
public class SerializeReferenceBehaviour : MonoBehaviour
{
[SerializeReference] TestSerializeObject o0;
[SerializeReference] TestSerializeObject o1;
[SerializeReference] TestSerializeObject o2;
[SerializeReference] TestSerializeObject o3;
[SerializeReference] TestSerializeObject o4;
[SerializeReference] TestSerializeObject o5;
#if UNITY_EDITOR
// Call this method when creating a prefab in the editor to initialize the values.
[UnityEditor.MenuItem("CONTEXT/SerializeReferenceBehaviour/Initialize SerializeReference")]
static void InitializeSerializeReference(UnityEditor.MenuCommand command)
{
var behaviour = command.context as SerializeReferenceBehaviour;
Debug.Assert(behaviour != null);
behaviour.o0 = new() { i0 = 0, i1 = 1, i2 = 2, i3 = 3, i4 = 4, i5 = 5 };
behaviour.o1 = new() { i0 = 0, i1 = 1, i2 = 2, i3 = 3, i4 = 4, i5 = 5 };
behaviour.o2 = new() { i0 = 0, i1 = 1, i2 = 2, i3 = 3, i4 = 4, i5 = 5 };
behaviour.o3 = new() { i0 = 0, i1 = 1, i2 = 2, i3 = 3, i4 = 4, i5 = 5 };
behaviour.o4 = new() { i0 = 0, i1 = 1, i2 = 2, i3 = 3, i4 = 4, i5 = 5 };
behaviour.o5 = new() { i0 = 0, i1 = 1, i2 = 2, i3 = 3, i4 = 4, i5 = 5 };
UnityEditor.EditorUtility.SetDirty(behaviour);
}
#endif
}
SerializePerformanceTester.cs
using UnityEngine;
public class SerializePerformanceTester : MonoBehaviour
{
const int testNum = 100000;
public bool testSerializeField;
public SerializeFieldBehaviour serializeFieldPrefab;
public SerializeReferenceBehaviour serializeReferencePrefab;
void Start()
{
if (testSerializeField)
Debug.Log("Test SerializeField");
else
Debug.Log("Test SerializeReference");
var sw = System.Diagnostics.Stopwatch.StartNew();
if (testSerializeField)
{
for (int i = 0; i < testNum; i++)
Instantiate(serializeFieldPrefab);
}
else
{
for (int i = 0; i < testNum; i++)
Instantiate(serializeReferencePrefab);
}
sw.Stop();
Debug.Log($"Elapsed : {sw.Elapsed}");
}
}
Test results
| Backend |
SerializeField (sec) |
SerializeReference (sec) |
| Editor |
3.8213440 |
10.1807955 |
| Mono |
1.1837976 |
3.9963540 |
| IL2CPP |
0.9641599 |
2.9475725 |
A test in the editor with a single field in the above code (i.e., removing o1 to o5).
| Backend |
SerializeField (sec) |
SerializeReference (sec) |
| Editor |
3.3694590 |
5.5051361 |