I have a MonoBehaviour that has two GUID fields in it. I set those through the custom inspector, but for some reason, it doesn’t store the changes into the component, so when I hit play or save the scene the values disappear.
I’m setting the target to be dirty in my custom inspector, and I have also tried to mark the GUIDs with [SerializeField].
Any one has any insight on this?
EDIT:
I’ve solved the problem by storing the GUID as string. This still doesn’t explain the issue though, would love an explanation.
The Guid type is not a basic data type. Just read the documentation of SerializeField. There’s a list of types which Unity can serialize.
Unity only serializes basic datatypes and basic datatype-variables in custom classes when the class has a Serializable attribute. Guid is not a class, it’s a struct, so that’s the first reason why it isn’t serialized. Unity can only serialize custom classes. The second reason is, all the GUID parts are private members (shorts). Private members aren’t serliazed unless they have the SerializeField attribute.
SerializeField can only be used for fields of a supported type.
I know this is an ancient question, but here is an example of how to create a wrapper class and custom propery draw-er to work around this restriction.
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(StringyGuid))]
public class StringyGuidDrawer : PropertyDrawer {
bool DO_VALIDATION = true;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
EditorGUI.BeginProperty(position, label, property);
position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
var indent = EditorGUI.indentLevel;
EditorGUI.indentLevel = 0;
var storageProp = property.FindPropertyRelative("m_storage");
if (DO_VALIDATION) {
var oldval = storageProp.stringValue;
var newval = EditorGUI.DelayedTextField(position, oldval);
if (oldval != newval) {
try {
storageProp.stringValue = new System.Guid(newval).ToString("D");
} catch (System.FormatException) {}
}
} else {
EditorGUI.PropertyField(position, storageProp, GUIContent.none);
}
EditorGUI.indentLevel = indent;
EditorGUI.EndProperty();
}
}
#endif
[System.Serializable]
public struct StringyGuid {
[SerializeField]
private string m_storage;
public static implicit operator StringyGuid(System.Guid rhs) {
return new StringyGuid { m_storage = rhs.ToString("D") };
}
public static implicit operator System.Guid(StringyGuid rhs) {
if (rhs.m_storage == null) return System.Guid.Empty;
try {
return new System.Guid(rhs.m_storage);
} catch (System.FormatException) {
return System.Guid.Empty;
}
}
}