using System.Collections.Generic; using UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif namespace BulletHellTemplate { /// /// Runtime helper that lets developers inspect and modify a single PlayerPrefs key /// while the game is running. Attach it to any GameObject in the scene. /// public class PlayerPrefsDebugger : MonoBehaviour { [Tooltip("PlayerPrefs key to inspect or edit.")] public string key = string.Empty; [Tooltip("The value type stored under this key.")] public PrefValueType valueType = PrefValueType.Int; [Tooltip("New value to assign when pressing Set Value.")] public string newValue = string.Empty; /// /// Returns the value currently stored under in PlayerPrefs. /// public string CurrentValue { get { switch (valueType) { case PrefValueType.Int: return PlayerPrefs.GetInt(key, 0).ToString(); case PrefValueType.Float: return PlayerPrefs.GetFloat(key, 0f).ToString(); default: return PlayerPrefs.GetString(key, string.Empty); } } } /// /// The three basic value types supported by Unity's PlayerPrefs API. /// public enum PrefValueType { Int, Float, String } /// /// Writes to PlayerPrefs using and /// the currently selected . The method includes basic /// parsing validation for numeric values. /// public void SetValue() { if (string.IsNullOrEmpty(key)) { Debug.LogWarning("Key is empty. Nothing was written."); return; } switch (valueType) { case PrefValueType.Int: if (int.TryParse(newValue, out int i)) PlayerPrefs.SetInt(key, i); else Debug.LogError($"'{newValue}' is not a valid integer."); break; case PrefValueType.Float: if (float.TryParse(newValue, out float f)) PlayerPrefs.SetFloat(key, f); else Debug.LogError($"'{newValue}' is not a valid float."); break; default: PlayerPrefs.SetString(key, newValue); break; } PlayerPrefs.Save(); } } #if UNITY_EDITOR /// /// Polished inspector for . It is defined inside /// a UNITY_EDITOR block so that it is only compiled for the Editor, never for builds. /// [CustomEditor(typeof(PlayerPrefsDebugger))] public class PlayerPrefsDebuggerInspector : Editor { SerializedProperty keyProp; SerializedProperty typeProp; SerializedProperty valueProp; void OnEnable() { keyProp = serializedObject.FindProperty("key"); typeProp = serializedObject.FindProperty("valueType"); valueProp = serializedObject.FindProperty("newValue"); } public override void OnInspectorGUI() { serializedObject.Update(); EditorGUILayout.PropertyField(keyProp, new GUIContent("Key")); EditorGUILayout.PropertyField(typeProp, new GUIContent("Value Type")); EditorGUILayout.PropertyField(valueProp, new GUIContent("New Value")); GUILayout.Space(4); if (GUILayout.Button("Get Current Value")) { var dbg = (PlayerPrefsDebugger)target; string current = dbg.CurrentValue; EditorUtility.DisplayDialog("Current Value", $"Key: {dbg.key}\nValue: {current}", "OK"); } if (GUILayout.Button("Set Value")) { ((PlayerPrefsDebugger)target).SetValue(); } serializedObject.ApplyModifiedProperties(); } } /// /// Stand‑alone window that offers a quick way to read, write and delete any /// PlayerPrefs key. Open it via Tools ▸ BulletHell Template ▸ PlayerPrefs Editor. /// public class PlayerPrefsEditorWindow : EditorWindow { private string key = string.Empty; private PlayerPrefsDebugger.PrefValueType valueType = PlayerPrefsDebugger.PrefValueType.Int; private string value = string.Empty; private Vector2 scroll; [MenuItem("Tools/BulletHell Template/PlayerPrefs Editor", priority = 1)] public static void Open() { GetWindow("PlayerPrefs Editor"); } void OnGUI() { GUILayout.Label("Key Editor", EditorStyles.boldLabel); key = EditorGUILayout.TextField("Key", key); valueType = (PlayerPrefsDebugger.PrefValueType)EditorGUILayout.EnumPopup("Value Type", valueType); value = EditorGUILayout.TextField("Value", value); GUILayout.BeginHorizontal(); if (GUILayout.Button("Get")) { value = GetCurrentValue(); } if (GUILayout.Button("Set")) { SetCurrentValue(); } if (GUILayout.Button("Delete")) { if (EditorUtility.DisplayDialog("Delete Key?", $"Remove '{key}' from PlayerPrefs?", "Yes", "No")) { PlayerPrefs.DeleteKey(key); PlayerPrefs.Save(); value = string.Empty; } } GUILayout.EndHorizontal(); GUILayout.Space(10); GUILayout.Label("Known Keys (read‑only)", EditorStyles.boldLabel); scroll = GUILayout.BeginScrollView(scroll); foreach (var kv in GetPrefixedKeys()) { GUILayout.BeginHorizontal(EditorStyles.helpBox); GUILayout.Label(kv.Key, GUILayout.Width(300)); GUILayout.Label(kv.Value); GUILayout.EndHorizontal(); } GUILayout.EndScrollView(); } string GetCurrentValue() { switch (valueType) { case PlayerPrefsDebugger.PrefValueType.Int: return PlayerPrefs.GetInt(key, 0).ToString(); case PlayerPrefsDebugger.PrefValueType.Float: return PlayerPrefs.GetFloat(key, 0f).ToString(); default: return PlayerPrefs.GetString(key, string.Empty); } } void SetCurrentValue() { switch (valueType) { case PlayerPrefsDebugger.PrefValueType.Int: if (int.TryParse(value, out int i)) PlayerPrefs.SetInt(key, i); else ShowParseError("int"); break; case PlayerPrefsDebugger.PrefValueType.Float: if (float.TryParse(value, out float f)) PlayerPrefs.SetFloat(key, f); else ShowParseError("float"); break; default: PlayerPrefs.SetString(key, value); break; } PlayerPrefs.Save(); } void ShowParseError(string type) { EditorUtility.DisplayDialog("Parsing Error", $"Value is not a valid {type}.", "OK"); } /// /// Because Unity does not expose PlayerPrefs enumeration at runtime, we rely on /// known prefixes defined in to probe for existing keys. /// IDictionary GetPrefixedKeys() { var dict = new Dictionary(); string[] prefixes = { "PLAYERNAME_", "PLAYERICON_", "PLAYERFRAME_", "PLAYERACCOUNTLEVEL_", "PLAYERACCOUNTCURRENTEXP_", "TUTORIALISDONE_", "PLAYERSELECTEDCHARACTER_", "PLAYERFAVOURITECHARACTER_", "CHARACTERMASTERYLEVEL_", "CHARACTERMASTERYCURRENTEXP_", "CHARACTERLEVEL_", "CHARACTERCURRENTEXP_", "ITEMSLOT_", "ITEMLEVEL_", "CHARACTERUPGRADELEVEL_", "CHARACTERSKIN_", "CHARACTERUNLOCKEDSKINS_", "UNLOCKED_MAPS", "QUEST_PROGRESS_", "QUEST_COMPLETED_", "USED_COUPONS_", "LOCAL_DAILYREWARDS_DATA", "LOCAL_NEWPLAYERREWARDS_DATA", "NEXTDAILYRESETTIME" }; foreach (string prefix in prefixes) { if (PlayerPrefs.HasKey(prefix)) dict[prefix] = SafeRead(prefix); if (prefix.EndsWith("_")) { for (int i = 0; i < 100; i++) { string keyVariant = prefix + i; if (PlayerPrefs.HasKey(keyVariant)) dict[keyVariant] = SafeRead(keyVariant); } } } return dict; } string SafeRead(string k) { // Try int int intVal = PlayerPrefs.GetInt(k, int.MinValue); if (intVal != int.MinValue) return intVal.ToString(); // Try float float floatVal = PlayerPrefs.GetFloat(k, float.NaN); if (!float.IsNaN(floatVal)) return floatVal.ToString(); // Fallback string return PlayerPrefs.GetString(k, string.Empty); } } #endif }