#if !COMBAT_SERVER using System; using System.Collections; using System.Collections.Generic; using UnityEngine; //Object并非C#基础中的Object,而是 UnityEngine.Object using Object = UnityEngine.Object; #if UNITY_EDITOR using UnityEditor; #endif namespace Fort23.Mono { //使其能在Inspector面板显示,并且可以被赋予相应值 [Serializable] public class ReferenceCollectorData { public string key; //Object并非C#基础中的Object,而是 UnityEngine.Object public Object gameObject; //是否对文件夹打AB包 public bool isAssetBundle; public bool isList; [NonReorderable] public List ListCollectorDatas = new List(); } [Serializable] public class ReferenceListCollectorData { public Object gameObject; } //继承IComparer对比器,Ordinal会使用序号排序规则比较字符串,因为是byte级别的比较,所以准确性和性能都不错 public class ReferenceCollectorDataComparer : IComparer { public int Compare(ReferenceCollectorData x, ReferenceCollectorData y) { return string.Compare(x.key, y.key, StringComparison.Ordinal); } } //继承ISerializationCallbackReceiver后会增加OnAfterDeserialize和OnBeforeSerialize两个回调函数,如果有需要可以在对需要序列化的东西进行操作 //ET在这里主要是在OnAfterDeserialize回调函数中将data中存储的ReferenceCollectorData转换为dict中的Object,方便之后的使用 //注意UNITY_EDITOR宏定义,在编译以后,部分编辑器相关函数并不存在 public class ReferenceCollector : MonoBehaviour, ISerializationCallbackReceiver { //用于序列化的List public List data = new List(); public bool isAssetBundle = true; // public GameObject //Object并非C#基础中的Object,而是 UnityEngine.Object private readonly Dictionary dict = new Dictionary(); #if UNITY_EDITOR //添加新的元素 public void Add(string key, Object obj) { SerializedObject serializedObject = new SerializedObject(this); //根据PropertyPath读取数据 //如果不知道具体的格式,可以右键用文本编辑器打开一个prefab文件(如Bundles/UI目录中的几个) //因为这几个prefab挂载了ReferenceCollector,所以搜索data就能找到存储的数据 SerializedProperty dataProperty = serializedObject.FindProperty(nameof(data)); int i; //遍历data,看添加的数据是否存在相同key for (i = 0; i < data.Count; i++) { if (data[i].key == key) { break; } } //不等于data.Count意为已经存在于data List中,直接赋值即可 if (i != data.Count) { //根据i的值获取dataProperty,也就是data中的对应ReferenceCollectorData,不过在这里,是对Property进行的读取,有点类似json或者xml的节点 SerializedProperty element = dataProperty.GetArrayElementAtIndex(i); //对对应节点进行赋值,值为gameobject相对应的fileID //fileID独一无二,单对单关系,其他挂载在这个gameobject上的script或组件会保存相对应的fileID element.FindPropertyRelative(nameof(gameObject)).objectReferenceValue = obj; } else { //等于则说明key在data中无对应元素,所以得向其插入新的元素 dataProperty.InsertArrayElementAtIndex(i); SerializedProperty element = dataProperty.GetArrayElementAtIndex(i); element.FindPropertyRelative(nameof(key)).stringValue = key; element.FindPropertyRelative(nameof(gameObject)).objectReferenceValue = obj; } //应用与更新 EditorUtility.SetDirty(this); serializedObject.ApplyModifiedProperties(); serializedObject.UpdateIfRequiredOrScript(); } //删除元素,知识点与上面的添加相似 public void Remove(string key) { SerializedObject serializedObject = new SerializedObject(this); SerializedProperty dataProperty = serializedObject.FindProperty(nameof(data)); int i; for (i = 0; i < data.Count; i++) { if (data[i].key == key) { break; } } if (i != data.Count) { dataProperty.DeleteArrayElementAtIndex(i); } EditorUtility.SetDirty(this); serializedObject.ApplyModifiedProperties(); serializedObject.UpdateIfRequiredOrScript(); } public void Clear() { SerializedObject serializedObject = new SerializedObject(this); //根据PropertyPath读取prefab文件中的数据 //如果不知道具体的格式,可以直接右键用文本编辑器打开,搜索data就能找到 var dataProperty = serializedObject.FindProperty(nameof(data)); dataProperty.ClearArray(); EditorUtility.SetDirty(this); serializedObject.ApplyModifiedProperties(); serializedObject.UpdateIfRequiredOrScript(); } public void Sort() { SerializedObject serializedObject = new SerializedObject(this); data.Sort(new ReferenceCollectorDataComparer()); EditorUtility.SetDirty(this); serializedObject.ApplyModifiedProperties(); serializedObject.UpdateIfRequiredOrScript(); } #endif //使用泛型返回对应key的gameobject public T Get(string key) where T : class { object dictGo; if (!dict.TryGetValue(key, out dictGo)) { return null; } return dictGo as T; } public Dictionary GetDict() { return dict; } public List GetData() { return data; } public object GetObject(string key) { object dictGo; if (!dict.TryGetValue(key, out dictGo)) { return null; } return dictGo; } public void OnBeforeSerialize() { } //在反序列化后运行 public void OnAfterDeserialize() { dict.Clear(); foreach (ReferenceCollectorData referenceCollectorData in data) { if (referenceCollectorData.isList) { List objvalue = new List(); for (int i = 0; i < referenceCollectorData.ListCollectorDatas.Count; i++) { objvalue.Add(referenceCollectorData.ListCollectorDatas[i].gameObject); } if (!dict.ContainsKey(referenceCollectorData.key)) { dict.Add(referenceCollectorData.key, objvalue); } } else { if (!dict.ContainsKey(referenceCollectorData.key)) { dict.Add(referenceCollectorData.key, referenceCollectorData.gameObject); } } } } } } #endif