When my scripts recompile or I enter play mode, my custom class gets reset

This class gets reset every time I save a script and tab back into unity. My Debug.Log(“create”); appears in the console in the editor when I tab back in, to be clear. I have a scrip that has a public property of AdvancedAnimationCurve(). I tried disabling the custom editor of the object that is holding the instance. I tried diabling the custom property drawer of the class below. I tried setting the private fields in the classes below with [SerializeField]. I even tried setting the variable within my script that has the AdvancedAnimationCurve() with [SerializeField]. Im not sure what else to try…

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;



[Serializable]
public class AdvancedAnimationCurve {

	public List<AdvAnimCurveKeyframe> keys;

	public bool editorUpdate;//Set to true when a keyframe is modified to let the editor know to redraw. Editor sets it to false on render.

	public AdvancedAnimationCurve() {
		Debug.Log("create");
		keys = new List<AdvAnimCurveKeyframe>() { new AdvAnimCurveKeyframe(this, 0, 0), new AdvAnimCurveKeyframe(this, 1, 1) };
		keys[0].RightTangentTime = Mathf.Sin((90 + (90 * .6666666f)) * Mathf.Deg2Rad);
		keys[0].RightTangentValue = Mathf.Cos((90 + (90 * .6666666f)) * Mathf.Deg2Rad);
		keys[1].LeftTangentTime = 1 - Mathf.Sin((90 + (90 * -.6666666f)) * Mathf.Deg2Rad);
		keys[1].LeftTangentValue = 1 - Mathf.Cos((90 + (90 * -.6666666f)) * Mathf.Deg2Rad);
	}

	public AdvAnimCurveKeyframe GetKey(int index) {
		return keys[index];
	}

	public void SetKey(int index, float value) {
		if (index < 0 || index > keys.Count - 1) {
			Debug.LogError("SetKey action cannot be completed. Arry index out of range.");
			return;
		}
		keys[index].MainValue = value;
	}

	/// <summary>
	/// Adds a key to the keyframes of the graph.
	/// </summary>
	/// <param name="time">The x value of the keyframe.</param>
	/// <param name="value">The y value of the keyframe.</param>
	/// <param name="replaceValue">If the time exists, replace value?</param>
	public void AddKey(float time, float value, bool replaceValue) {
		for (int i = 0; i < keys.Count - 1; i++) {
			if (keys*.MainTime == time) {*
  •  		if (replaceValue)*
    

_ keys*.MainValue = value;_
_
return;_
_
}_
_
}_
_
for (int i = 0; i < keys.Count - 1; i++) {_
_ if (time > keys.MainTime && time < keys[i + 1].MainTime) {
Debug.Log("inserting at " + i);
keys.Insert(i + 1, new AdvAnimCurveKeyframe(this, time, value));
return;
}
}
keys.Add(new AdvAnimCurveKeyframe(this, time, value));
}*_

* ///

*
* /// This is used internally to tell the editor script to redraw on keyframe modification.*
* ///
*
* public void KeyframeChanged() {*
* editorUpdate = true;*
* }*

}

[Serializable]
public class AdvAnimCurveKeyframe {

* private AdvancedAnimationCurve home;*

* private float mainTime, leftTangentTime, rightTangentTime, mainValue, leftTangentValue, rightTangentValue;*

* public AdvAnimCurveKeyframe(AdvancedAnimationCurve home, float mainTime, float mainValue) {*
* this.home = home;*
* this.mainTime = mainTime;*
* this.mainValue = mainValue;*
* home.KeyframeChanged();*
* }*

* public float MainTime {*
* get { return mainTime; }*
* set { mainTime = value; home.KeyframeChanged(); }*
* }*
* public float MainValue {*
* get { return mainValue; }*
* set { mainValue = value; home.KeyframeChanged(); }*
* }*
* public float LeftTangentTime {*
* get { return leftTangentTime; }*
* set { leftTangentTime = value; home.KeyframeChanged(); }*
* }*
* public float LeftTangentValue {*
* get { return leftTangentValue; }*
* set { leftTangentValue = value; home.KeyframeChanged(); }*
* }*
* public float RightTangentTime {*
* get { return rightTangentTime; }*
* set { rightTangentTime = value; home.KeyframeChanged(); }*
* }*
* public float RightTangentValue {*
* get { return rightTangentValue; }*
* set { rightTangentValue = value; home.KeyframeChanged(); }*
* }*

* public Vector2 Main {*
* get { return new Vector2(mainTime, mainValue); }*
* }*
* public Vector2 LeftTangent {*
* get { return new Vector2(leftTangentTime, leftTangentValue); }*
* }*
* public Vector2 RightTangent {*
* get { return new Vector2(rightTangentTime, rightTangentValue); }*
* }*

}

Well there are several problems. First and formost the fields of your "AdvAnimCurveKeyframe " class are private and therefore not serialized as they don’t have a SerializeField attribute. If you want those fields to be serialized but not automatically show up in the inspector you can do:

[SerializeField, HideInInspector]
private float someField;

The next potential problem is your “home” reference. It must not be serialized as otherwise you would have a circular reference between your two classes. This is not supported for custom classes. Only inside the editor in some edge cases the editor will also serialized private fields if possible (playmode change / assembly hot reload).

Custom classes are not serialized on their own but as part of the MonoBehaviour / ScriptableObject that contains a field of that type. Custom serializable classes behave like “structs”. So there’s no polymorphism support. Also references to other custom serializable classes are not stored as “references” but as “sub-fields”. The serializer has a maximum nesting level of 7. Though a circular reference is never supported.

It’s bad practise to only put in a reference to another class that isn’t even used at runtime. It seems you have either a custom inspector or property drawer for your class(es). So it would make more sense to detect the changes there. Alternatively you could use a static bool which gets set to true in your setters. That way there’s no need to reference the curve from the keyframes.