/// <summary>
        /// Will create copies of everything in the object's reference graph using the following rules: anything
        /// Unity can serialize (see Unity documentation on serialization for a complete list), but also
        /// ScriptableObjects that are either direct references, or otherwise contained in a serializable type
        /// belonging to the previous category. So as of this writing, a field containing a scriptable object adorned
        /// with [SerializeField] or public, contained in an array or list, or a field in a serializable custom class
        /// will be copied. Examples where a scriptable object will not be copied: as keys or values in a dictionary,
        /// in a non-public field not marked with [SerializeField], in a non-serializable class.
        /// </summary>
        public static T CopyDeep <T>(this T obj) where T : ScriptableObject
        {
            obj = obj.CopyShallow();
            var serializedObject = new SerializedObject(obj);
            var iterator         = serializedObject.GetIterator();

            iterator.Next(true);
            while (iterator.NextVisible(true))
            {
                if (iterator.propertyType == SerializedPropertyType.ObjectReference)
                {
                    ScriptableObject so = iterator.objectReferenceValue as ScriptableObject;
                    if (so != null)
                    {
                        so = so.CopyDeep();
                        iterator.objectReferenceValue = so;
                    }
                }
            }
            serializedObject.ApplyModifiedProperties();
            return((T)serializedObject.targetObject);
        }