Skip to content

Commit 31f9a27

Browse files
committed
Auto populate default values for unity-serialized fields
1 parent 726ee9c commit 31f9a27

File tree

2 files changed

+62
-3
lines changed

2 files changed

+62
-3
lines changed

Editor/TriPropertyDefinition.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public class TriPropertyDefinition
1818
private readonly List<string> _extensionErrors = new List<string>();
1919
private readonly MemberInfo _memberInfo;
2020
private readonly List<Attribute> _attributes;
21+
private readonly bool _isNonPolymorphicSerializedByUnity;
2122

2223
private TriPropertyDefinition _arrayElementDefinitionBackingField;
2324

@@ -73,6 +74,10 @@ internal TriPropertyDefinition(
7374
_valueGetter = valueGetter;
7475
_valueSetter = valueSetter;
7576

77+
_isNonPolymorphicSerializedByUnity = memberInfo is FieldInfo fi &&
78+
TriUnitySerializationUtilities.IsSerializableByUnity(fi) &&
79+
fi.GetCustomAttribute<SerializeReference>() == null;
80+
7681
Order = order;
7782
IsReadOnly = _valueSetter == null || Attributes.TryGet(out ReadOnlyAttribute _);
7883

@@ -143,7 +148,19 @@ public bool TryGetMemberInfo(out MemberInfo memberInfo)
143148

144149
public object GetValue(TriProperty property, int targetIndex)
145150
{
146-
return _valueGetter(property, targetIndex);
151+
var value = _valueGetter(property, targetIndex);
152+
153+
if (value == null && _isNonPolymorphicSerializedByUnity)
154+
{
155+
value = TriUnitySerializationUtilities.PopulateUnityDefaultValueForType(FieldType);
156+
157+
if (value != null)
158+
{
159+
_valueSetter?.Invoke(property, targetIndex, value);
160+
}
161+
}
162+
163+
return value;
147164
}
148165

149166
public bool SetValue(TriProperty property, object value, int targetIndex, out object parentValue)

Editor/Utilities/TriUnitySerializationUtilities.cs

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections;
23
using System.Collections.Generic;
34
using System.Reflection;
45
using UnityEngine;
@@ -23,13 +24,13 @@ public static bool IsSerializableByUnity(FieldInfo fieldInfo)
2324

2425
if (fieldInfo.IsPublic || fieldInfo.GetCustomAttribute<SerializeField>() != null)
2526
{
26-
return IsTypeSerializable(fieldInfo.FieldType, allowCollections: true);
27+
return IsTypeSerializable(fieldInfo.FieldType);
2728
}
2829

2930
return false;
3031
}
3132

32-
private static bool IsTypeSerializable(Type type, bool allowCollections)
33+
public static bool IsTypeSerializable(Type type, bool allowCollections = true)
3334
{
3435
if (type == typeof(object))
3536
{
@@ -97,6 +98,11 @@ private static bool IsTypeSerializable(Type type, bool allowCollections)
9798
}
9899
}
99100

101+
if (typeof(IEnumerable).IsAssignableFrom(type))
102+
{
103+
return false;
104+
}
105+
100106
if (type.GetCustomAttribute<SerializableAttribute>() != null)
101107
{
102108
return true;
@@ -106,5 +112,41 @@ private static bool IsTypeSerializable(Type type, bool allowCollections)
106112

107113
return false;
108114
}
115+
116+
internal static object PopulateUnityDefaultValueForType(Type type)
117+
{
118+
if (type == typeof(string))
119+
{
120+
return string.Empty;
121+
}
122+
123+
if (typeof(Object).IsAssignableFrom(type))
124+
{
125+
return null;
126+
}
127+
128+
if (type.IsEnum)
129+
{
130+
var values = Enum.GetValues(type);
131+
return values.Length > 0 ? values.GetValue(0) : Enum.ToObject(type, 0);
132+
}
133+
134+
if (type.IsValueType)
135+
{
136+
return Activator.CreateInstance(type);
137+
}
138+
139+
if (type.IsArray && type.GetElementType() is var elementType && elementType != null)
140+
{
141+
return Array.CreateInstance(elementType, 0);
142+
}
143+
144+
if (type.GetConstructor(Type.EmptyTypes) != null)
145+
{
146+
return Activator.CreateInstance(type);
147+
}
148+
149+
return null;
150+
}
109151
}
110152
}

0 commit comments

Comments
 (0)