https://github.com/kastro723/PlayerPrefsViewer
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
public class PlayerPrefsViewer : EditorWindow
{
private Vector2 scrollPosition;
private string newKey = "";
private string newValue = "";
private int selectedTypeIndex = 0;
private string[] typeOptions = { "String", "Int", "Float" };
private Dictionary<string, (string Value, PlayerPrefsManager.ValueType Type)> playerPrefsCache = new Dictionary<string, (string, PlayerPrefsManager.ValueType)>();
private List<string> keysToRemove = new List<string>(); // 삭제할 키들을 저장할 리스트
[MenuItem("Tools/Player Prefs Viewer")]
public static void ShowWindow()
{
var window = GetWindow<PlayerPrefsViewer>("Player Prefs Viewer");
window.maxSize = new Vector2(495, window.maxSize.y);
window.minSize = new Vector2(495, 300);
window.Show();
}
void OnEnable() // 창이 열리거나 포커스를 받을 때 이벤트 구독
{
PlayerPrefsManager.OnPreferencesUpdated += RefreshPlayerPrefsCache;
}
void OnDisable() // 창이 닫히거나 포커스를 잃을 때 메모리 누수를 방지하기 위해 이벤트 구독 해제
{
PlayerPrefsManager.OnPreferencesUpdated -= RefreshPlayerPrefsCache;
}
void OnGUI()
{
GUILayout.Label("Ver. 1.0.0", EditorStyles.boldLabel);
DrawLine();
if (GUILayout.Button("Refresh List"))
{
RefreshPlayerPrefsCache();
}
scrollPosition = GUILayout.BeginScrollView(scrollPosition);
List<string> toRemove = new List<string>(); // 삭제할 항목을 임시 저장할 리스트
foreach (var kvp in playerPrefsCache)
{
GUILayout.BeginHorizontal();
GUILayout.Label(kvp.Key, GUILayout.Width(100));
GUILayout.Label(kvp.Value.Value, GUILayout.Width(200));
GUILayout.Label(kvp.Value.Type.ToString(), GUILayout.Width(50));
if (GUILayout.Button("Modify", GUILayout.Width(60)))
{
PlayerPrefsEditWindow.Open(kvp.Key, kvp.Value.Value, kvp.Value.Type);
}
if (GUILayout.Button("Remove", GUILayout.Width(60)))
{
bool confirm = EditorUtility.DisplayDialog("Confirm Removal", $"Are you sure you want to remove {kvp.Key}?", "Yes", "No");
if (confirm)
{
toRemove.Add(kvp.Key); // 삭제 리스트에 추가
}
}
GUILayout.EndHorizontal();
}
GUILayout.EndScrollView();
foreach (var key in toRemove)
{
PlayerPrefsManager.Instance.RemoveKey(key);
playerPrefsCache.Remove(key); // 캐시에서도 삭제
}
DrawAddKeyValueSection();
if (GUILayout.Button("Remove All"))
{
bool confirm = EditorUtility.DisplayDialog("Confirm Removal", "Are you sure you want to remove all PlayerPrefs?", "Yes", "No");
if (confirm)
{
PlayerPrefsManager.Instance.ClearAll();
RefreshPlayerPrefsCache();
}
}
ProcessRemovals(); // 삭제할 키들을 리스트에 모은 다음, GUI 이벤트 처리가 모두 끝난 후에 한 번에 삭제를 처리
}
private void RefreshPlayerPrefsCache()
{
playerPrefsCache.Clear();
var allKeys = PlayerPrefsManager.Instance.GetAllKeys();
foreach (var key in allKeys)
{
var type = PlayerPrefsManager.Instance.GetType(key);
string value = "";
switch (type)
{
case PlayerPrefsManager.ValueType.String:
value = PlayerPrefsManager.Instance.GetString(key);
break;
case PlayerPrefsManager.ValueType.Int:
value = PlayerPrefsManager.Instance.GetInt(key).ToString();
break;
case PlayerPrefsManager.ValueType.Float:
value = PlayerPrefsManager.Instance.GetFloat(key).ToString();
break;
}
playerPrefsCache[key] = (value, type);
}
}
private void DrawAddKeyValueSection()
{
GUILayout.Space(10);
DrawLine();
GUILayout.Space(10);
GUILayout.BeginHorizontal();
GUILayout.Label("Key", GUILayout.Width(100));
GUILayout.Label("Value", GUILayout.Width(200));
GUILayout.Label("Type", GUILayout.Width(200));
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
newKey = GUILayout.TextField(newKey, GUILayout.Width(100));
newValue = GUILayout.TextField(newValue, GUILayout.Width(200));
selectedTypeIndex = EditorGUILayout.Popup(selectedTypeIndex, typeOptions, GUILayout.Width(70));
if (GUILayout.Button("Add", GUILayout.Width(105)))
{
AddKeyValue();
}
GUILayout.EndHorizontal();
}
private void AddKeyValue()
{
if (!string.IsNullOrEmpty(newKey))
{
// 이미 존재하는 키인지 확인
if (PlayerPrefsManager.Instance.GetAllKeys().Contains(newKey))
{
EditorUtility.DisplayDialog("Duplicate Key", "A key with the same name already exists. Please use a different key.", "OK");
return;
}
PlayerPrefsManager.ValueType selectedType = (PlayerPrefsManager.ValueType)Enum.Parse(typeof(PlayerPrefsManager.ValueType), typeOptions[selectedTypeIndex]);
if (selectedType == PlayerPrefsManager.ValueType.Int)
{
if (int.TryParse(newValue, out int intValue))
{
PlayerPrefsManager.Instance.SetInt(newKey, intValue);
PlayerPrefsManager.Instance.SetType(newKey, selectedType);
}
else
{
EditorUtility.DisplayDialog("Invalid Value", "For an integer value, please enter a valid integer.", "OK");
return;
}
}
else if (selectedType == PlayerPrefsManager.ValueType.Float)
{
if (float.TryParse(newValue, out float floatValue))
{
PlayerPrefsManager.Instance.SetFloat(newKey, floatValue);
PlayerPrefsManager.Instance.SetType(newKey, selectedType);
}
else
{
EditorUtility.DisplayDialog("Invalid Value", "Please enter floating point values correctly.", "OK");
return;
}
}
else // String 타입 처리
{
PlayerPrefsManager.Instance.SetString(newKey, newValue);
PlayerPrefsManager.Instance.SetType(newKey, selectedType);
}
// 새로운 키 추가 후 필드 초기화
newKey = "";
newValue = "";
selectedTypeIndex = 0;
RefreshPlayerPrefsCache(); // PlayerPrefs 캐시 갱신
}
}
private void ProcessRemovals()
{
foreach (var key in keysToRemove)
{
PlayerPrefsManager.Instance.RemoveKey(key);
}
if (keysToRemove.Count > 0)
{
RefreshPlayerPrefsCache();
keysToRemove.Clear();
}
}
private void DrawLine()
{
EditorGUI.DrawRect(EditorGUILayout.GetControlRect(false, 1), Color.gray);
}
}
using System;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class KeysWrapper
{
public List<string> keys;
}
public class PlayerPrefsManager
{
private static PlayerPrefsManager instance;
public static PlayerPrefsManager Instance
{
get
{
if (instance == null)
{
instance = new PlayerPrefsManager();
instance.LoadKeys();
}
return instance;
}
}
public static event Action OnPreferencesUpdated;
// 이벤트를 트리거하는 메서드 추가 (캡슐화로 인해 직접적인 호출이 불가능하기 때문)
public static void TriggerPreferencesUpdated()
{
OnPreferencesUpdated?.Invoke();
}
///
private HashSet<string> keys = new HashSet<string>();
private const string KeyStore = "PlayerPrefsKeys";
public enum ValueType
{
String,
Int,
Float
}
private PlayerPrefsManager() { }
public void SetString(string key, string value)
{
PlayerPrefs.SetString(key, value);
AddKey(key);
PlayerPrefs.Save();
}
public string GetString(string key, string defaultValue = "")
{
return PlayerPrefs.GetString(key, defaultValue);
}
public void SetInt(string key, int value)
{
PlayerPrefs.SetInt(key, value);
AddKey(key);
PlayerPrefs.Save();
}
public int GetInt(string key, int defaultValue = 0)
{
return PlayerPrefs.GetInt(key, defaultValue);
}
public void SetFloat(string key, float value)
{
PlayerPrefs.SetFloat(key, value);
AddKey(key);
PlayerPrefs.Save();
}
public float GetFloat(string key, float defaultValue = 0f)
{
return PlayerPrefs.GetFloat(key, defaultValue);
}
public void RemoveKey(string key)
{
PlayerPrefs.DeleteKey(key);
keys.Remove(key);
SaveKeys();
}
public void ClearAll()
{
PlayerPrefs.DeleteAll();
keys.Clear();
SaveKeys();
}
public HashSet<string> GetAllKeys()
{
return keys;
}
private void AddKey(string key)
{
if (keys.Add(key))
{
SaveKeys();
}
}
private void SaveKeys()
{
KeysWrapper keysWrapper = new KeysWrapper { keys = new List<string>(keys) };
var json = JsonUtility.ToJson(keysWrapper);
PlayerPrefs.SetString(KeyStore, json);
PlayerPrefs.Save();
TriggerPreferencesUpdated();
}
private void LoadKeys()
{
var json = PlayerPrefs.GetString(KeyStore, "{}");
KeysWrapper keysWrapper = JsonUtility.FromJson<KeysWrapper>(json);
if (keysWrapper != null && keysWrapper.keys != null)
{
keys = new HashSet<string>(keysWrapper.keys);
}
else
{
keys = new HashSet<string>();
}
}
public void SetType(string key, ValueType type)
{
PlayerPrefs.SetString(key + "_type", type.ToString());
PlayerPrefs.Save();
}
public ValueType GetType(string key)
{
var typeStr = PlayerPrefs.GetString(key + "_type", ValueType.String.ToString());
return (ValueType)Enum.Parse(typeof(ValueType), typeStr);
}
}
using UnityEditor;
using UnityEngine;
public class PlayerPrefsEditWindow : EditorWindow
{
private string originalKey;
private string originalValue; // 원래 값 보관을 위한 변수
private PlayerPrefsManager.ValueType originalType;
private string key;
private string value;
private PlayerPrefsManager.ValueType selectedType;
public static void Open(string key, string value, PlayerPrefsManager.ValueType type)
{
var window = GetWindow<PlayerPrefsEditWindow>("Modify PlayerPrefs");
window.originalKey = key;
window.originalValue = value; // 원래 값 초기화
window.originalType = type; // 원래 타입 초기화
window.key = key;
window.value = value;
window.selectedType = type;
window.Show();
}
void OnGUI()
{
EditorGUILayout.LabelField("Current Key-Value Pair", EditorStyles.boldLabel);
EditorGUILayout.LabelField("Key: " + originalKey);
EditorGUILayout.LabelField("Value: " + originalValue);
EditorGUILayout.LabelField("Type: " + originalType.ToString());
EditorGUILayout.Space();
EditorGUILayout.LabelField("Modify Key-Value Pair", EditorStyles.boldLabel);
GUI.enabled = false;
key = EditorGUILayout.TextField("Key", key);
GUI.enabled = true;
value = EditorGUILayout.TextField("Value", value);
selectedType = (PlayerPrefsManager.ValueType)EditorGUILayout.EnumPopup("Type", selectedType);
if (GUILayout.Button("Modify"))
{
if (EditorUtility.DisplayDialog("Confirm Modification", "Do you want to modify this PlayerPrefs entry?", "Yes", "No"))
{
ModifyPlayerPrefs();
}
}
}
private void ModifyPlayerPrefs()
{
if (selectedType == PlayerPrefsManager.ValueType.String)
{
PlayerPrefsManager.Instance.SetString(key, value);
PlayerPrefsManager.Instance.SetType(key, PlayerPrefsManager.ValueType.String);
}
else if (selectedType == PlayerPrefsManager.ValueType.Int && int.TryParse(value, out int intValue))
{
PlayerPrefsManager.Instance.SetInt(key, intValue);
PlayerPrefsManager.Instance.SetType(key, PlayerPrefsManager.ValueType.Int);
}
else if (selectedType == PlayerPrefsManager.ValueType.Float && float.TryParse(value, out float floatValue))
{
PlayerPrefsManager.Instance.SetFloat(key, floatValue);
PlayerPrefsManager.Instance.SetType(key, PlayerPrefsManager.ValueType.Float); // 타입 정보 업데이트
}
else
{
EditorUtility.DisplayDialog("Invalid Input", "The provided value does not match the selected type.", "OK");
return;
}
PlayerPrefsManager.TriggerPreferencesUpdated();
Close();
}
}
'UnityDataTools' 카테고리의 다른 글
Random Seed Generator (0) | 2024.03.24 |
---|---|
MoveToFileEditor (0) | 2024.03.21 |
[UnityDataTools] Big Number Converter - 리얼 숫자 변환/역변환 + 계산기 (0) | 2024.02.22 |
[UnityDataTools] JsonHierarchy Viewer (0) | 2024.02.15 |
[UnityDataTools] Excel to JSON Converter - 파일 자동 변환 도구 (xlsx -> json, cs) (0) | 2024.02.14 |