I need to be able to save my game’s settings to disk, so I’m going to serialize the settings object then save it to disk, and overwrite it at the game’s startup. I’ve already tried Newtonsoft, and that either gives me a recursive loop error or causes the editor to crash when I click play (if I add a flag to serialize that loop). So far, the only output I get from JsonUtility.ToJson()
is “{}”, no matter what sort of object I use. I really DON’T want to use PlayerPrefs, as that will
-
Make it harder for me to fix
settings if I can’t load the game -
Make it impossible for players to edit settings
-
Make it a real pain in the butt to have to rewrite all of my code
Here’s my code (very long, have removed some useless stuff):
[Serializable]
public class SingletonSettings : MonoBehaviour
{
#region This makes sure there aren't any other instances running
public static SingletonSettings Instance;
void Awake()
{
if (Instance == null)
Instance = this;
else
Destroy(gameObject);
}
#endregion
#region Initialise other classes
public static _Sensitivity Sensitivity = new _Sensitivity();
public static _Graphics Graphics = new _Graphics();
public static _Sound Sound = new _Sound();
public static _Input Input = new _Input();
static SingletonSettings test;
#endregion
void Start()
{
test = this;
Gameplay.Functions.HideCursor();
Gameplay.Functions.SetGameSpeed(1);
}
void FixedUpdate()
{
//Increase game time each tick
Gameplay.Functions.SetGameSpeed(Gameplay.Functions.GetGameTime() + 1);
Debug.Log(JsonUtility.ToJson(test));
}
}
[Serializable]
public class _Sensitivity
{
public float vertical = 1;
public float horizontal = 1;
}
[Serializable]
public class _Input
{
#region Keybindings
public KeyCode[] Forward = { KeyCode.W };
public KeyCode[] Back = { KeyCode.S };
public KeyCode[] Left = { KeyCode.A };
public KeyCode[] Right = { KeyCode.D };
public KeyCode[] Jump = { KeyCode.Space };
public KeyCode[] Crouch = { KeyCode.LeftControl };
public KeyCode[] Sprint = { KeyCode.LeftShift };
public KeyCode[] Fire = { KeyCode.Mouse0 };
public KeyCode[] SwapView = { KeyCode.F5 };
public KeyCode[] Menu = { KeyCode.Escape };
#endregion
#region GetKeyDown
private bool _GetKeyDown(KeyCode[] keys)
{
bool pressed = true;
foreach (KeyCode k in keys)
{
pressed = Input.GetKeyDown(k) ? pressed : false;
}
return pressed;
}
public bool GetKeyDown(KeyCode[] keys)
{
return _GetKeyDown(keys);
}
public bool GetKeyDown(KeyCode key)
{
KeyCode[] b = { key };
return _GetKeyDown(b);
}
#endregion
#region GetKeyUp
private bool _GetKeyUp(KeyCode[] keys)
{
foreach (KeyCode k in keys)
{
if (Input.GetKeyUp(k))
return false;
}
return true;
}
public bool GetKeyUp(KeyCode[] keys)
{
return _GetKeyUp(keys);
}
public bool GetKeyUp(KeyCode key)
{
KeyCode[] b = { key };
return _GetKeyUp(b);
}
#endregion
#region GetAxis
[SerializeField]
private Dictionary<KeyCode[], float> positiveLastVal = new Dictionary<KeyCode[], float>();
[SerializeField]
Dictionary<KeyCode[], float> negativeLastVal = new Dictionary<KeyCode[], float>();
private float _GetAxis(KeyCode[] positive, KeyCode[] negative, float smoothing = 10F)
{
smoothing = smoothing != 0 ? 1 / smoothing : 0;
float p = Convert.ToSingle(_GetKey(positive)), n = Convert.ToSingle(_GetKey(negative));
//If values do not exist in dictionary, add them
if (!positiveLastVal.ContainsKey(positive))
positiveLastVal.Add(positive, p);
if (!negativeLastVal.ContainsKey(negative))
negativeLastVal.Add(negative, p);
//If no smoothing, skip it
if (smoothing == 0)
{
positiveLastVal[positive] = p;
negativeLastVal[negative] = n;
}
else
{
positiveLastVal[positive] = Mathf.Lerp(positiveLastVal[positive], p, smoothing);
negativeLastVal[negative] = Mathf.Lerp(negativeLastVal[negative], n, smoothing);
}
//Load values from dictionary to variables
float pos = positiveLastVal[positive];
float neg = negativeLastVal[negative];
return pos - neg;
}
public float GetAxis(KeyCode[] positive, KeyCode[] negative, float smoothing = 10F)
{
return Convert.ToSingle(_GetAxis(positive, negative, smoothing));
}
public float GetAxis(KeyCode positive, KeyCode negative, float smoothing = 10F)
{
KeyCode[] a = { positive };
KeyCode[] b = { negative };
return Convert.ToSingle(_GetAxis(a, b, smoothing));
}
#endregion
#region GetKey
private bool _GetKey(KeyCode[] keys)
{
foreach (KeyCode k in keys)
{
if (!Input.GetKey(k))
return false;
}
return true;
}
public bool GetKey(KeyCode[] keys)
{
return _GetKey(keys);
}
public bool GetKey(KeyCode key)
{
KeyCode[] b = { key };
return _GetKey(b);
}
#endregion
}
If I serialize one of the objects inside, like Input
, then I get an output, but that is not what I would like. I would much prefer if there was a way to serialize Instance
instead