zxl
/
CTT
forked from Cal/CTT
1
0
Fork 0
CTT/Unity/Assets/Model/Other/ReferenceCollector.cs

158 lines
5.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.Collections.Generic;
#if !ROBOT
using UnityEngine;
using UnityEditor;
//Object并非C#基础中的Object而是 UnityEngine.Object
using Object = UnityEngine.Object;
//使其能在Inspector面板显示并且可以被赋予相应值
[Serializable]
public class ReferenceCollectorData
{
public string key;
//Object并非C#基础中的Object而是 UnityEngine.Object
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>();
//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就能找到
SerializedProperty 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 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 (!dict.ContainsKey(referenceCollectorData.key))
{
dict.Add(referenceCollectorData.key, referenceCollectorData.gameObject);
}
}
}
}
#endif