| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 | #if !COMBAT_SERVERusing System;using System.Collections;using System.Collections.Generic;using UnityEngine;//Object并非C#基础中的Object,而是 UnityEngine.Objectusing Object = UnityEngine.Object;#if UNITY_EDITORusing UnityEditor;#endifnamespace 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<ReferenceListCollectorData> ListCollectorDatas = new List<ReferenceListCollectorData>();    }    [Serializable]    public class ReferenceListCollectorData    {        public Object gameObject;    }    //继承IComparer对比器,Ordinal会使用序号排序规则比较字符串,因为是byte级别的比较,所以准确性和性能都不错    public class ReferenceCollectorDataComparer : IComparer<ReferenceCollectorData>    {        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<ReferenceCollectorData> data = new List<ReferenceCollectorData>();        public bool isAssetBundle = true;        // public GameObject         //Object并非C#基础中的Object,而是 UnityEngine.Object        private readonly Dictionary<string, object> dict = new Dictionary<string, object>();#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("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("gameObject").objectReferenceValue = obj;            }            else            {                //等于则说明key在data中无对应元素,所以得向其插入新的元素                dataProperty.InsertArrayElementAtIndex(i);                SerializedProperty element = dataProperty.GetArrayElementAtIndex(i);                element.FindPropertyRelative("key").stringValue = key;                element.FindPropertyRelative("gameObject").objectReferenceValue = obj;            }            //应用与更新            EditorUtility.SetDirty(this);            serializedObject.ApplyModifiedProperties();            serializedObject.UpdateIfRequiredOrScript();        }        //删除元素,知识点与上面的添加相似        public void Remove(string key)        {            SerializedObject serializedObject = new SerializedObject(this);            SerializedProperty dataProperty = serializedObject.FindProperty("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("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<T>(string key) where T : class        {            object dictGo;            if (!dict.TryGetValue(key, out dictGo))            {                return null;            }            return dictGo as T;        }        public Dictionary<string, object> GetDict()        {            return dict;        }        public List<ReferenceCollectorData> 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<object> objvalue = new List<object>();                    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
 |