using System; using Unity.Collections.LowLevel.Unsafe; using UnityEngine; using UnityEngine.Assertions; namespace RosettaUI { public static class PersistentData { private class Wrapper { public T value; } public static bool HasKey(string key) { return PlayerPrefs.HasKey(key); } public static bool TryGet(string key, out T value) { if (HasKey(key)) { value = Get(key); return true; } value = default; return false; } public static T Get(string key) { var type = typeof(T); if (type == typeof(int)) return GetInt(key); if (type == typeof(float)) return GetFloat(key); if (type == typeof(bool)) return GetBool(key); if (type == typeof(string)) return GetString(key); return GetAny(key); } public static void Set(string key, T value) { var type = typeof(T); if (type == typeof(int)) { SetInt(key, value); } else if (type == typeof(float)) { SetFloat(key, value); } else if (type == typeof(bool)) { SetBool(key, value); } else if (type == typeof(string)) { SetString(key, value); } else { SetAny(key, value); } } private static T GetInt(string key) { var intValue = PlayerPrefs.GetInt(key); return UnsafeUtility.As(ref intValue); } private static void SetInt(string key, T value) { var intValue = UnsafeUtility.As(ref value); PlayerPrefs.SetInt(key, intValue); } private static T GetFloat(string key) { var floatValue = PlayerPrefs.GetFloat(key); return UnsafeUtility.As(ref floatValue); } private static void SetFloat(string key, T value) { Assert.IsTrue(typeof(T) == typeof(float)); var floatValue = UnsafeUtility.As(ref value); PlayerPrefs.SetFloat(key, floatValue); } private static T GetString(string key) { var stringValue = PlayerPrefs.GetString(key); return UnsafeUtility.As(ref stringValue); } private static void SetString(string key, T value) { Assert.IsTrue(typeof(T) == typeof(string)); var stringValue = UnsafeUtility.As(ref value); PlayerPrefs.SetString(key, stringValue); } private static T GetBool(string key) { var intValue = PlayerPrefs.GetInt(key); var boolValue = intValue != 0; return UnsafeUtility.As(ref boolValue); } private static void SetBool(string key, T value) { Assert.IsTrue(typeof(T) == typeof(bool)); var boolValue = UnsafeUtility.As(ref value); var intValue = boolValue ? 1 : 0; PlayerPrefs.SetInt(key, intValue); } private static T GetAny(string key) { if (!PlayerPrefs.HasKey(key)) { return default; } var json = PlayerPrefs.GetString(key); try { var wrapper = JsonUtility.FromJson>(json); return wrapper.value; } catch (Exception e) { Debug.LogWarning($"Failed to parse {key} as {typeof(T)}: {e}"); } return default; } private static void SetAny(string key, T value) { var wrapper = new Wrapper { value = value }; var json = JsonUtility.ToJson(wrapper); PlayerPrefs.SetString(key, json); } } }