SerializedProperty.animationCurveValue cannot be set directly

Assigning a value to the animationCurveValue property of an instance of the SerializedProperty class will cause an error stating that the value that is being assigned is not an animation curve even if it is. How can I fix or circumvent this?


Containing class

[CustomPropertyDrawer(typeof(SerializedAnimationCurve))]
public class CustomCurveDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        EditorGUI.BeginProperty(position, label, property);

        var amountRect = new Rect(position.x, position.y + EditorGUIUtility.singleLineHeight, position.width, position.height);
        var curveRect = new Rect(position.x - position.width, position.y + EditorGUIUtility.singleLineHeight, position.width, position.height);

        SerializedProperty templateCurveProperty = property.FindPropertyRelative("template");
        SerializedProperty curveProperty = property.FindPropertyRelative("curve");

        EditorGUI.PropertyField(new Rect(position.x, position.y, position.width - 6, 15), curveProperty, label);

        Rect indentRect = EditorGUI.IndentedRect(position);

        Object templateValue = templateCurveProperty.objectReferenceValue;

        EditorGUI.PropertyField(new Rect(indentRect.x + 15, indentRect.y + 20, indentRect.width - 21, 15), templateCurveProperty, new GUIContent("Template"));
        if (templateValue != templateCurveProperty.objectReferenceValue)
        {
            SerializedObject serializedObject = new SerializedObject(templateCurveProperty.objectReferenceValue);

            AnimationCurve templateCurve = ((SerializableAnimationCurveObject)templateCurveProperty.objectReferenceValue).curve;
            SerializedProperty objCurveProperty = serializedObject.FindProperty("curve");

            //Debug.Log(templateCurve);
            //Debug.Log(serializedObject.FindProperty("curve").animationCurveValue);

            objCurveProperty.animationCurveValue = templateCurve;
            serializedObject.ApplyModifiedProperties();
        }
        EditorGUI.EndProperty();
    }
    public override float GetPropertyHeight(SerializedProperty prop, GUIContent label)
    {
        float extraHeight = 25f;
        return base.GetPropertyHeight(prop, label) + extraHeight;
    }
}

Referenced Classes

[System.Serializable]
[CreateAssetMenu(fileName = "AnimCurve", menuName = "Curve")]
public class SerializableAnimationCurveObject : ScriptableObject
{
    public string curveName;

    public AnimationCurve curve;

    private void OnEnable()
    {
        curveName = name;
    }

    public static implicit operator AnimationCurve(SerializableAnimationCurveObject serializableCurve)
    {
        return serializableCurve.curve;
    }

    public static implicit operator SerializedAnimationCurve(SerializableAnimationCurveObject serializableCurve)
    {
        return new SerializedAnimationCurve(serializableCurve);
    }
}

[System.Serializable]
public class SerializedAnimationCurve
{
    public string curveName;
    public AnimationCurve curve;
    public SerializableAnimationCurveObject template;

    public SerializedAnimationCurve(SerializableAnimationCurveObject template)
    {
        this.template = template;
        curveName = template.curveName;
        curve = template.curve;
    }
}

Problem snippet

SerializedObject serializedObject = templateCurveProperty.serializedObject;
            AnimationCurve templateCurve = ((SerializableAnimationCurveObject)templateCurveProperty.objectReferenceValue).curve;
            SerializedProperty objCurveProperty = serializedObject.FindProperty("curve");

            Debug.Log(templateCurve);
            Debug.Log(serializedObject.FindProperty("curve").animationCurveValue);

            objCurveProperty.animationCurveValue = templateCurve;
            serializedObject.ApplyModifiedProperties();

Prints the following statements

Based on your response above, the problem is that you are trying to set animationCurveValue on a serialized property that does not actually refer to an animation curve.

It’s hard to say without more context, but from your example it looks like SerializableAnimationCurveObject is a ScriptableObject. If that’s the case, you need to get a separate serialized data stream for it. Something like this:

var templateSO = new SerializedObject(templateCurveProperty.objectReferenceValue);
var curveProperty = templateSO.FindProperty("curve");
curveProperty.animationCurveValue = templateCurve;
templateSO.ApplyModifiedProperties();