using System; using System.Collections.Generic; using System.IO; using System.Threading.Tasks; using Newtonsoft.Json; using UnityEditor; using UnityEngine; using System.Linq; namespace Stary.Evo.InformationSave { public abstract class AbstractInformation : CustomEditorBase where T : InformationBase, new() { [HideInInspector] public List _list = new List(); /// /// 配置文件存储路径 /// string path = "InformationSaveData/ScriptObjectSaveData"; public virtual void Add() { _list.Add(new T()); Save(_list.Count - 1); } public abstract void Save(int index); public abstract void Switch(int index); public virtual T GetTransform(string desc) { int index = _list.FindIndex(n => n.desc == desc); if (index != -1) { return _list[index]; } else { Debug.LogError($"UnityEvo:{typeof(T)}:不存在该信息:" + desc); return default(T); } } public virtual void Delete(int index) { _list.RemoveAt(index); } public virtual void Set(string desc) { int index = _list.FindIndex(n => n.desc == desc); if (index != -1) Switch(index); } #region Editor #if UNITY_EDITOR //更新 public void UpdateInformation() { string guid = GetPrefabGUID(this.gameObject)+GetPrefabHierarchyPath(this.gameObject); if (guid == "") { UnityEditor.EditorUtility.DisplayDialog("错误", "可能存在错误\n1、无法在prefab预览中修改数据\n2、新增加物体需先同步为prefab", "确定"); return; } ScriptObjectSave scriptObjectSaveData = Resources.Load(path); if (scriptObjectSaveData == null) { Debug.LogError("UnityEvo:ScriptObjectSaveData配置文件丢失"); return; } if (scriptObjectSaveData.dic.ContainsKey(guid)) { _list.Clear(); _list = scriptObjectSaveData.dic[guid].OfType().ToList(); } else { Debug.LogError($"UnityEvo:ScriptObjectSaveData中未存储物体名为:{this.gameObject}\n guid为:{guid}的数据!!!"); } } //动态保存 public bool PlayingSave() { //文件保存 string guid = GetPrefabGUID(this.gameObject)+GetPrefabHierarchyPath(this.gameObject); if (guid == "") { UnityEditor.EditorUtility.DisplayDialog("错误", "可能存在错误\n1、无法在prefab预览中修改数据\n2、新增加物体需先同步为prefab", "确定"); return false; } // 加载 ScriptObjectSaveData ScriptObjectSave scriptObjectSaveData = Resources.Load(path); if (scriptObjectSaveData == null) { scriptObjectSaveData = CheckAndCreateFoldersAndAsset(); //Debug.Log("创建了ScriptObjectSaveData文件"); } if (scriptObjectSaveData.dic == null) { Debug.LogError("UnityEvo:ScriptObjectSaveData的dic为空"); return false; } // 检查是否已经存在相同的键 if (scriptObjectSaveData.dic.ContainsKey(guid)) { // 如果存在,选择是否替换原有的 List if (UnityEditor.EditorUtility.DisplayDialog("提示", $"数据集下已有相同名称的物体数据\n是否覆盖更新!!!\n 物体名为:{this.gameObject}\n guid为:{guid}", "确定", "取消")) { scriptObjectSaveData.dic[guid] = new List(_list); } else { return false; } } else { // 如果不存在,添加新的键值对 scriptObjectSaveData.dic.Add(guid, new List(_list)); } AssetDatabase.SaveAssets(); EditorUtility.SetDirty(scriptObjectSaveData); AssetDatabase.Refresh(); return true; } private ScriptObjectSave CheckAndCreateFoldersAndAsset() { string ResourcesFolderName = "Resources"; string InformationSaveDataFolderName = "InformationSaveData"; string ScriptObjectSaveDataFileName = "ScriptObjectSaveData"; ScriptObjectSave scriptableObject; // 判断是否创建Resources文件夹 string resourcesPath = Path.Combine(Application.dataPath, ResourcesFolderName); if (!Directory.Exists(resourcesPath)) { Directory.CreateDirectory(resourcesPath); } // 判断是否创建InformationSaveData文件夹 string informationSaveDataPath = Path.Combine(resourcesPath, InformationSaveDataFolderName); if (!Directory.Exists(informationSaveDataPath)) { Directory.CreateDirectory(informationSaveDataPath); } // 创建ScriptObjectSaveData.asset文件 scriptableObject = ScriptableObject.CreateInstance(); AssetDatabase.CreateAsset(scriptableObject, "Assets/" + ResourcesFolderName + "/" + InformationSaveDataFolderName + "/" + ScriptObjectSaveDataFileName + ".asset"); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); Debug.Log("UnityEvo:创建了: " + "Assets/" + ResourcesFolderName + "/" + InformationSaveDataFolderName + "/" + ScriptObjectSaveDataFileName + ".asset 资产"); return scriptableObject; } //绘制 public override void Draw() { int length = _list.Count; int deleteIndex = -1; for (int i = 0; i < length; i++) { GUILayout.BeginHorizontal(); _list[i].desc = UnityEditor.EditorGUILayout.TextField(_list[i].desc); if (GUILayout.Button("切换")) Switch(i); if (GUILayout.Button("保存")) { Save(i); if (PlayingSave()) Debug.Log("UnityEvo:保存成功!"); } if (GUILayout.Button("上移") && i > 0) { T temp = _list[i - 1]; _list[i - 1] = _list[i]; _list[i] = temp; } if (GUILayout.Button("下移") && i < _list.Count - 1) { T temp = _list[i + 1]; _list[i + 1] = _list[i]; _list[i] = temp; } if (GUILayout.Button("删除") && UnityEditor.EditorUtility.DisplayDialog("警告", "你确定要删除吗?", "确定", "取消")) deleteIndex = i; GUILayout.EndHorizontal(); if (i != length - 1) GUILayout.Space(20); } if (deleteIndex != -1) Delete(deleteIndex); GUILayout.Space(30); GUILayout.BeginHorizontal(); if (GUILayout.Button("添加")) { Add(); } if (GUILayout.Button("更新") && UnityEditor.EditorUtility.DisplayDialog("提示", "你确定要更新吗?", "确定", "取消")) { UpdateInformation(); GUILayout.BeginHorizontal(); } GUILayout.EndHorizontal(); } private string GetCurrentGUID() { string assetPath = AssetDatabase.GetAssetPath(this); if (!string.IsNullOrEmpty(assetPath)) { return AssetDatabase.AssetPathToGUID(assetPath); } return string.Empty; } private string GetPrefabGUID(GameObject obj) { string assetPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(obj); Debug.Log("UnityEvo:GetPrefabHierarchyPath:" + GetPrefabHierarchyPath(obj)); if (!string.IsNullOrEmpty(assetPath)) { return AssetDatabase.AssetPathToGUID(assetPath); } return string.Empty; } private string GetPrefabHierarchyPath(GameObject obj) { var path = new System.Text.StringBuilder(); var current = obj.transform; //检测该预制体是否是实例 var root = PrefabUtility.GetNearestPrefabInstanceRoot(obj); if (root != null) { while (current != null && current != root.transform) { path.Insert(0, current.name); path.Insert(0, "/"); current = current.parent; } return path.ToString(); } return string.Empty; } #else public override void Draw(){} #endif } #endregion [System.Serializable] public class InformationBase { public string desc = "初始"; } }