#if UNITY_EDITOR using UnityEditor; using UnityEngine; using System.Reflection; using System.Collections.Generic; using System; using System.Collections; using System.IO; public class PlayerDataEditorWindow : EditorWindow { private AccountFileInfo.PlayerData playerData; private Vector2 scrollPos; private Dictionary foldoutStates = new Dictionary(); private string DataFilePath = "/playerData.txt"; [MenuItem("Tools/PlayerData 编辑器")] public static void ShowWindow() { GetWindow(true,"PlayerData 编辑器"); } private void OnEnable() { LoadPlayerData(); } private void OnGUI() { GUIStyle headerStyle = new GUIStyle(EditorStyles.boldLabel) { fontSize = 14, padding = new RectOffset(5, 5, 5, 5) }; GUIStyle sectionStyle = new GUIStyle(EditorStyles.helpBox) { margin = new RectOffset(5, 5, 5, 5), padding = new RectOffset(10, 10, 10, 10) }; scrollPos = EditorGUILayout.BeginScrollView(scrollPos); if (playerData == null) { EditorGUILayout.HelpBox("未加载 PlayerData!点击下方创建新数据。", MessageType.Warning); if (GUILayout.Button("创建新 PlayerData", GUILayout.Height(30))) { playerData = new AccountFileInfo.PlayerData(); } EditorGUILayout.EndScrollView(); return; } EditorGUILayout.LabelField("PlayerData 编辑器", headerStyle); EditorGUILayout.Space(); EditorGUILayout.BeginVertical(sectionStyle); try { DrawFields(playerData, playerData.GetType(), "PlayerData."); } catch (Exception ex) { EditorGUILayout.HelpBox($"绘制字段时出错: {ex.Message}", MessageType.Error); } EditorGUILayout.EndVertical(); EditorGUILayout.Space(); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("保存 PlayerData", GUILayout.Height(30))) { if (EditorUtility.DisplayDialog("保存确认", $"确定要保存到 {Application.persistentDataPath + DataFilePath}?\n现有文件将被覆盖。", "确定", "取消")) { SavePlayerData(); } } if (GUILayout.Button("加载 PlayerData", GUILayout.Height(30))) { if (EditorUtility.DisplayDialog("加载确认", $"确定要从 {Application.persistentDataPath + DataFilePath} 加载数据?\n当前编辑的数据将被覆盖。", "确定", "取消")) { LoadPlayerData(); } } EditorGUILayout.EndHorizontal(); EditorGUILayout.EndScrollView(); } private void DrawFields(object obj, Type type, string prefix = "") { if (obj == null) { EditorGUILayout.LabelField($"{prefix} (空)"); return; } FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance); foreach (FieldInfo field in fields) { string fieldKey = $"{prefix}{field.Name}"; object value = field.GetValue(obj); // 初始化折叠状态 if (!foldoutStates.ContainsKey(fieldKey)) foldoutStates[fieldKey] = false; // 处理基本类型 if (field.FieldType == typeof(int)) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField(field.Name, GUILayout.Width(200)); int newValue = EditorGUILayout.IntField(value != null ? (int)value : 0); field.SetValue(obj, newValue); EditorGUILayout.EndHorizontal(); } else if (field.FieldType == typeof(long)) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField(field.Name, GUILayout.Width(200)); long newValue = EditorGUILayout.LongField(value != null ? (long)value : 0); field.SetValue(obj, newValue); EditorGUILayout.EndHorizontal(); } else if (field.FieldType == typeof(bool)) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField(field.Name, GUILayout.Width(200)); bool newValue = EditorGUILayout.Toggle(value != null ? (bool)value : false); field.SetValue(obj, newValue); EditorGUILayout.EndHorizontal(); } else if (field.FieldType == typeof(float)) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField(field.Name, GUILayout.Width(200)); float newValue = EditorGUILayout.FloatField(value != null ? (float)value : 0f); field.SetValue(obj, newValue); EditorGUILayout.EndHorizontal(); } else if (field.FieldType == typeof(string)) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField(field.Name, GUILayout.Width(200)); string newValue = EditorGUILayout.TextField(value != null ? (string)value : ""); field.SetValue(obj, newValue); EditorGUILayout.EndHorizontal(); } // 处理列表类型 else if (field.FieldType.IsGenericType && field.FieldType.GetGenericTypeDefinition() == typeof(List<>)) { Type itemType = field.FieldType.GetGenericArguments()[0]; IList list = (IList)(value ?? Activator.CreateInstance(field.FieldType)); EditorGUILayout.BeginHorizontal(); foldoutStates[fieldKey] = EditorGUILayout.Foldout(foldoutStates[fieldKey], $"{field.Name} (列表, {list.Count} 项)", true); EditorGUILayout.EndHorizontal(); if (foldoutStates[fieldKey]) { EditorGUI.indentLevel++; EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("大小", GUILayout.Width(200)); int newSize = EditorGUILayout.IntField(list.Count); try { while (newSize > list.Count) { object newItem = Activator.CreateInstance(itemType); list.Add(newItem); } while (newSize < list.Count) { list.RemoveAt(list.Count - 1); } } catch (Exception ex) { EditorGUILayout.HelpBox($"修改列表大小时出错: {ex.Message}", MessageType.Error); } EditorGUILayout.EndHorizontal(); for (int i = 0; i < list.Count; i++) { string itemKey = $"{fieldKey}[{i}]"; if (!foldoutStates.ContainsKey(itemKey)) foldoutStates[itemKey] = false; EditorGUILayout.BeginHorizontal(); foldoutStates[itemKey] = EditorGUILayout.Foldout(foldoutStates[itemKey], $"{field.Name}[{i}]", true); if (GUILayout.Button("删除", GUILayout.Width(60))) { list.RemoveAt(i); foldoutStates.Remove(itemKey); break; } EditorGUILayout.EndHorizontal(); if (foldoutStates[itemKey]) { EditorGUI.indentLevel++; EditorGUILayout.BeginVertical(EditorStyles.helpBox); try { DrawFields(list[i], itemType, $"{prefix}{field.Name}[{i}]."); } catch (Exception ex) { EditorGUILayout.HelpBox($"绘制 {itemKey} 时出错: {ex.Message}", MessageType.Error); } EditorGUILayout.EndVertical(); EditorGUI.indentLevel--; } } if (GUILayout.Button($"添加新 {itemType.Name}", GUILayout.Height(25))) { try { object newItem = Activator.CreateInstance(itemType); list.Add(newItem); } catch (Exception ex) { EditorGUILayout.HelpBox($"添加新 {itemType.Name} 时出错: {ex.Message}", MessageType.Error); } } field.SetValue(obj, list); EditorGUI.indentLevel--; } } // 处理自定义类 else if (field.FieldType.IsClass) { EditorGUILayout.BeginHorizontal(); foldoutStates[fieldKey] = EditorGUILayout.Foldout(foldoutStates[fieldKey], $"{field.Name} ({field.FieldType.Name})", true); if (value == null && GUILayout.Button("创建", GUILayout.Width(60))) { value = Activator.CreateInstance(field.FieldType); field.SetValue(obj, value); } EditorGUILayout.EndHorizontal(); if (foldoutStates[fieldKey] && value != null) { EditorGUI.indentLevel++; EditorGUILayout.BeginVertical(EditorStyles.helpBox); try { DrawFields(value, field.FieldType, $"{prefix}{field.Name}."); } catch (Exception ex) { EditorGUILayout.HelpBox($"绘制 {fieldKey} 时出错: {ex.Message}", MessageType.Error); } EditorGUILayout.EndVertical(); EditorGUI.indentLevel--; } } else { EditorGUILayout.LabelField($"{field.Name} ({field.FieldType.Name})", "不支持的类型"); } } } private void SavePlayerData() { try { string json = JsonUtility.ToJson(playerData, true); string path = Application.persistentDataPath + DataFilePath; File.WriteAllText(path, json); Debug.Log($"PlayerData 已保存至 {path}"); EditorUtility.DisplayDialog("保存成功", $"PlayerData 已保存至 {path}", "确定"); } catch (Exception ex) { EditorGUILayout.HelpBox($"保存 PlayerData 时出错: {ex.Message}", MessageType.Error); EditorUtility.DisplayDialog("保存失败", $"保存 PlayerData 时出错: {ex.Message}", "确定"); } } private void LoadPlayerData() { if (!Application.isPlaying) { if(playerData == null) playerData = new AccountFileInfo.PlayerData(); try { string path = Application.persistentDataPath + DataFilePath; if (File.Exists(path)) { string json = File.ReadAllText(path); JsonUtility.FromJsonOverwrite(json, playerData); } else { EditorGUILayout.HelpBox($"未找到文件: {path}", MessageType.Warning); EditorUtility.DisplayDialog("加载失败", $"未找到文件: {path}", "确定"); } } catch (Exception ex) { EditorGUILayout.HelpBox($"加载 PlayerData 时出错: {ex.Message}", MessageType.Error); EditorUtility.DisplayDialog("加载失败", $"加载 PlayerData 时出错: {ex.Message}", "确定"); } } else { playerData = AccountFileInfo.Instance.playerData; } } } #endif