static RuntimePrefabPropertyOverride CreateMultiple <TContainer>(SerializedProperty property, string rootPropertyPath,
                                                                         string transformPath, int componentIndex, ref bool hasNext, ref bool shouldIterate, SerializationMetadata metadata)
            where TContainer : UnityObject
        {
            if (!hasNext)
            {
                Debug.LogError($"Tried to create {nameof(RuntimePrefabPropertyOverride)} with invalid iterator");
                return(null);
            }

            var listOverride = new RuntimePrefabPropertyOverrideList(rootPropertyPath, transformPath, componentIndex);
            var list         = listOverride.List;
            var startDepth   = property.depth;

            do
            {
                if (shouldIterate)
                {
                    hasNext = property.Next(true);
                    if (!hasNext)
                    {
                        break;
                    }
                }

                shouldIterate = true;

                var propertyPath = property.propertyPath;
                var depth        = property.depth;

                // Skip the .Array property to reduce nesting and avoid early-out based on depth check below
                if (depth == startDepth && propertyPath.EndsWith(".Array"))
                {
                    hasNext = property.Next(true);
                    if (!hasNext)
                    {
                        break;
                    }

                    depth        = property.depth;
                    propertyPath = property.propertyPath;
                }

                if (depth <= startDepth)
                {
                    break;
                }

                if (!property.prefabOverride)
                {
                    continue;
                }

                var propertyOverride = Create <TContainer>(property, propertyPath, transformPath, componentIndex,
                                                           ref hasNext, out shouldIterate, metadata);

                if (propertyOverride != null)
                {
                    list.Add(propertyOverride);
                }

                if (!hasNext)
                {
                    break;
                }
            }while (property.depth > startDepth);

            return(listOverride);
        }
        public static RuntimePrefabPropertyOverride Create <TValue>(string propertyPath, string transformPath,
                                                                    int componentIndex, TValue value, SerializationMetadata metadata = null)
        {
            switch (value)
            {
            case Vector2 vector2:
            {
                var @override = new RuntimePrefabPropertyOverrideList(propertyPath, transformPath, componentIndex);
                var list      = @override.List;
                list.Add(new RuntimePrefabOverrideFloat($"{propertyPath}.x", transformPath, componentIndex, vector2.x));
                list.Add(new RuntimePrefabOverrideFloat($"{propertyPath}.y", transformPath, componentIndex, vector2.y));
                return(@override);
            }

            case Vector3 vector3:
            {
                var @override = new RuntimePrefabPropertyOverrideList(propertyPath, transformPath, componentIndex);
                var list      = @override.List;
                list.Add(new RuntimePrefabOverrideFloat($"{propertyPath}.x", transformPath, componentIndex, vector3.x));
                list.Add(new RuntimePrefabOverrideFloat($"{propertyPath}.y", transformPath, componentIndex, vector3.y));
                list.Add(new RuntimePrefabOverrideFloat($"{propertyPath}.z", transformPath, componentIndex, vector3.z));
                return(@override);
            }

            case Vector4 vector4:
            {
                var @override = new RuntimePrefabPropertyOverrideList(propertyPath, transformPath, componentIndex);
                var list      = @override.List;
                list.Add(new RuntimePrefabOverrideFloat($"{propertyPath}.x", transformPath, componentIndex, vector4.x));
                list.Add(new RuntimePrefabOverrideFloat($"{propertyPath}.y", transformPath, componentIndex, vector4.y));
                list.Add(new RuntimePrefabOverrideFloat($"{propertyPath}.z", transformPath, componentIndex, vector4.z));
                list.Add(new RuntimePrefabOverrideFloat($"{propertyPath}.w", transformPath, componentIndex, vector4.w));
                return(@override);
            }

            case Quaternion quaternion:
            {
                var @override = new RuntimePrefabPropertyOverrideList(propertyPath, transformPath, componentIndex);
                var list      = @override.List;
                list.Add(new RuntimePrefabOverrideFloat($"{propertyPath}.x", transformPath, componentIndex, quaternion.x));
                list.Add(new RuntimePrefabOverrideFloat($"{propertyPath}.y", transformPath, componentIndex, quaternion.y));
                list.Add(new RuntimePrefabOverrideFloat($"{propertyPath}.z", transformPath, componentIndex, quaternion.z));
                list.Add(new RuntimePrefabOverrideFloat($"{propertyPath}.w", transformPath, componentIndex, quaternion.w));
                return(@override);
            }

            case Color color:
            {
                var @override = new RuntimePrefabPropertyOverrideList(propertyPath, transformPath, componentIndex);
                var list      = @override.List;
                list.Add(new RuntimePrefabOverrideFloat($"{propertyPath}.r", transformPath, componentIndex, color.r));
                list.Add(new RuntimePrefabOverrideFloat($"{propertyPath}.g", transformPath, componentIndex, color.g));
                list.Add(new RuntimePrefabOverrideFloat($"{propertyPath}.b", transformPath, componentIndex, color.b));
                list.Add(new RuntimePrefabOverrideFloat($"{propertyPath}.a", transformPath, componentIndex, color.a));
                return(@override);
            }

            case Color32 color:
            {
                var @override = new RuntimePrefabPropertyOverrideList(propertyPath, transformPath, componentIndex);
                var list      = @override.List;
                list.Add(new RuntimePrefabOverrideFloat($"{propertyPath}.r", transformPath, componentIndex, color.r));
                list.Add(new RuntimePrefabOverrideFloat($"{propertyPath}.g", transformPath, componentIndex, color.g));
                list.Add(new RuntimePrefabOverrideFloat($"{propertyPath}.b", transformPath, componentIndex, color.b));
                list.Add(new RuntimePrefabOverrideFloat($"{propertyPath}.a", transformPath, componentIndex, color.a));
                return(@override);
            }

            case string @string:
            {
                return(new RuntimePrefabOverrideString(propertyPath, transformPath, componentIndex, @string));
            }

            case char @char:
            {
                return(new RuntimePrefabOverrideChar(propertyPath, transformPath, componentIndex, @char));
            }

            case bool @bool:
            {
                return(new RuntimePrefabOverrideBool(propertyPath, transformPath, componentIndex, @bool));
            }

            case int @int:
            {
                return(new RuntimePrefabOverrideInt(propertyPath, transformPath, componentIndex, @int));
            }

            case long @long:
            {
                return(new RuntimePrefabOverrideLong(propertyPath, transformPath, componentIndex, @long));
            }

            case float @float:
            {
                return(new RuntimePrefabOverrideFloat(propertyPath, transformPath, componentIndex, @float));
            }

            case UnityObject unityObject:
            {
                return(new RuntimePrefabOverrideUnityObjectReference(propertyPath, transformPath, componentIndex,
                                                                     UnityObjectReference.GetReferenceForObject(unityObject, metadata)));
            }

            default:
            {
                // TODO: Handle null values better
                if (typeof(TValue) == typeof(UnityObject) && value == null)
                {
                    return(new RuntimePrefabOverrideUnityObjectReference(propertyPath, transformPath, componentIndex,
                                                                         UnityObjectReference.NullObjectReference));
                }

                throw new NotImplementedException();
            }
            }
        }