- Home /
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[i].MainTime == time) {
if (replaceValue)
keys[i].MainValue = value;
return;
}
}
for (int i = 0; i < keys.Count - 1; i++) {
if (time > keys[i].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));
}
/// <summary>
/// This is used internally to tell the editor script to redraw on keyframe modification.
/// </summary>
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); }
}
}
I also get this in the console. XD is the name of the instance of AdvancedAnimationCurve Serialization depth limit 7 exceeded at 'AdvAnimCurve$$anonymous$$eyframe.home'. There may be an object composition cycle in one or more of your serialized classes.
Serialization hierarchy:
8: AdvAnimCurve$$anonymous$$eyframe.home
7: AdvancedAnimationCurve.keys
6: AdvAnimCurve$$anonymous$$eyframe.home
5: AdvancedAnimationCurve.keys
4: AdvAnimCurve$$anonymous$$eyframe.home
3: AdvancedAnimationCurve.keys
2: AdvAnimCurve$$anonymous$$eyframe.home
1: AdvancedAnimationCurve.keys
0: NoobieAnimation.XD
Answer by Bunny83 · Aug 20, 2017 at 11:36 AM
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.
To better understand how Unity actually serializes your stuff, i suggest you set your "asset serialization mode" to "force text" (Edit --> Project Settings --> Editor --> Asset Serialization) . That way whatever asset contains your animation curve will be serialized as YA$$anonymous$$L text. Just open the scene, prefab or asset file with a text editor and find the $$anonymous$$onoBehaviour / ScriptableObject that contains your curve. There you will see that all serialized fields of your curve are just sub fields of the $$anonymous$$onoBehaviour / ScriptableObject.
If you prefer to read documentations i suggest to have a look at Asset serialization and make sure you read the important sections. ("hot reloading", "serialization rules" and "When might the serializer behave unexpectedly").
I removed the circular reference. I just use a static bool now. I also set the line of private variables to [SerializeField] in AdvAnimCurve$$anonymous$$eyframe. For some reason, the data still seems to not serialize. I think everything meets the criteria in the section on the page you linked me "How to ensure a custom class can be serialized", but no cigar.
It actually states that "A List of a simple field type that can be serialized", so is my list the problem?
Your answer
![](https://koobas.hobune.stream/wayback/20220612133128im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
How do you save changes made with custom editor? 3 Answers
Keeping object between edit and play modes. 1 Answer
Add lines to a script from another script 0 Answers
What would be the best way to go about loading and saving a Serializable object in JSON with Unity? 0 Answers
Base MonoBehaviour Editor, foldout with base properties, child properties untouched. 1 Answer