提交 a1c37f22 编写于 作者: M me66ccff 提交者: tanghai

添加ReferenceCollector相关注释 (#129)

* 添加ReferenceCollectorEditor.cs注释,昨天看了下ReferenceCollector的原理,感觉用来入门插件编写挺合适的,所以就写点注释给需要的人
上级 352d944d
using System;
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
//Object并非C#基础中的Object,而是 UnityEngine.Object
using Object = UnityEngine.Object;
//自定义ReferenceCollector类在界面中的显示与功能
[CustomEditor(typeof (ReferenceCollector))]
//没有该属性的编辑器在选中多个物体时会提示“Multi-object editing not supported”
[CanEditMultipleObjects]
public class ReferenceCollectorEditor: Editor
{
private string searchKey
//输入在textfield中的字符串
private string searchKey
{
get
{
......@@ -45,17 +49,23 @@ public class ReferenceCollectorEditor: Editor
private void OnEnable()
{
referenceCollector = (ReferenceCollector) target;
//将被选中的gameobject所挂载的ReferenceCollector赋值给编辑器类中的ReferenceCollector,方便操作
referenceCollector = (ReferenceCollector) target;
}
public override void OnInspectorGUI()
{
Undo.RecordObject(referenceCollector, "Changed Settings");
//使ReferenceCollector支持撤销操作,还有Redo,不过没有在这里使用
Undo.RecordObject(referenceCollector, "Changed Settings");
var dataProperty = serializedObject.FindProperty("data");
//开始水平布局,如果是比较新版本学习U3D的,可能不知道这东西,这个是老GUI系统的知识,除了用在编辑器里,还可以用在生成的游戏中
GUILayout.BeginHorizontal();
//下面几个if都是点击按钮就会返回true调用里面的东西
if (GUILayout.Button("添加引用"))
{
AddReference(dataProperty, Guid.NewGuid().GetHashCode().ToString(), null);
//添加新的元素,具体的函数注释
// Guid.NewGuid().GetHashCode().ToString() 就是新建后默认的key
AddReference(dataProperty, Guid.NewGuid().GetHashCode().ToString(), null);
}
if (GUILayout.Button("全部删除"))
{
......@@ -71,8 +81,11 @@ public class ReferenceCollectorEditor: Editor
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
searchKey = EditorGUILayout.TextField(searchKey);
EditorGUILayout.ObjectField(heroPrefab, typeof (Object), false);
//可以在编辑器中对searchKey进行赋值,只要输入对应的Key值,就可以点后面的删除按钮删除相对应的元素
searchKey = EditorGUILayout.TextField(searchKey);
//添加的可以用于选中Object的框,这里的object也是(UnityEngine.Object
//第三个参数为是否只能引用scene中的Object
EditorGUILayout.ObjectField(heroPrefab, typeof (Object), false);
if (GUILayout.Button("删除"))
{
referenceCollector.Remove(searchKey);
......@@ -83,21 +96,25 @@ public class ReferenceCollectorEditor: Editor
var delList = new List<int>();
SerializedProperty property;
//遍历ReferenceCollector中data list的所有元素,显示在编辑器中
for (int i = referenceCollector.data.Count - 1; i >= 0; i--)
{
GUILayout.BeginHorizontal();
//这里的知识点在ReferenceCollector中有说
property = dataProperty.GetArrayElementAtIndex(i).FindPropertyRelative("key");
EditorGUILayout.TextField(property.stringValue, GUILayout.Width(150));
property = dataProperty.GetArrayElementAtIndex(i).FindPropertyRelative("gameObject");
EditorGUILayout.ObjectField(property.objectReferenceValue, typeof(Object), true);
if (GUILayout.Button("X"))
{
//将元素添加进删除list
delList.Add(i);
}
GUILayout.EndHorizontal();
}
var eventType = Event.current.type;
if (eventType == EventType.DragUpdated || eventType == EventType.DragPerform)
//在Inspector 窗口上创建区域,向区域拖拽资源对象,获取到拖拽到区域的对象
if (eventType == EventType.DragUpdated || eventType == EventType.DragPerform)
{
// Show a copy icon on the drag
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
......@@ -113,6 +130,8 @@ public class ReferenceCollectorEditor: Editor
Event.current.Use();
}
//遍历删除list,将其删除掉
foreach (var i in delList)
{
dataProperty.DeleteArrayElementAtIndex(i);
......@@ -121,7 +140,8 @@ public class ReferenceCollectorEditor: Editor
serializedObject.UpdateIfRequiredOrScript();
}
private void AddReference(SerializedProperty dataProperty, string key, Object obj)
//添加元素,具体知识点在ReferenceCollector中说了
private void AddReference(SerializedProperty dataProperty, string key, Object obj)
{
int index = dataProperty.arraySize;
dataProperty.InsertArrayElementAtIndex(index);
......
using System;
using System;
using System.Collections.Generic;
using UnityEngine;
//Object并非C#基础中的Object,而是 UnityEngine.Object
using Object = UnityEngine.Object;
#if UNITY_EDITOR
using UnityEditor;
#endif
//使其能在Inspector面板显示,并且可以被赋予相应值
[Serializable]
public class ReferenceCollectorData
{
public string key;
public Object gameObject;
//Object并非C#基础中的Object,而是 UnityEngine.Object
public Object gameObject;
}
//继承IComparer对比器,Ordinal会使用序号排序规则比较字符串,因为是byte级别的比较,所以准确性和性能都不错
public class ReferenceCollectorDataComparer: IComparer<ReferenceCollectorData>
{
public int Compare(ReferenceCollectorData x, ReferenceCollectorData y)
......@@ -22,18 +25,27 @@ public class ReferenceCollectorDataComparer: IComparer<ReferenceCollectorData>
}
}
//继承ISerializationCallbackReceiver后会增加OnAfterDeserialize和OnBeforeSerialize两个回调函数,如果有需要可以在对需要序列化的东西进行操作
//ET在这里主要是在OnAfterDeserialize回调函数中将data中存储的ReferenceCollectorData转换为dict中的Object,方便之后的使用
//注意UNITY_EDITOR宏定义,在编译以后,部分编辑器相关函数并不存在
public class ReferenceCollector: MonoBehaviour, ISerializationCallbackReceiver
{
//用于序列化的List
public List<ReferenceCollectorData> data = new List<ReferenceCollectorData>();
private readonly Dictionary<string, Object> dict = new Dictionary<string, Object>();
//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);
SerializedProperty dataProperty = serializedObject.FindProperty("data");
//根据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)
......@@ -41,23 +53,29 @@ public class ReferenceCollector: MonoBehaviour, ISerializationCallbackReceiver
break;
}
}
if (i != data.Count)
//不等于data.Count意为已经存在于data List中,直接赋值即可
if (i != data.Count)
{
SerializedProperty element = dataProperty.GetArrayElementAtIndex(i);
element.FindPropertyRelative("gameObject").objectReferenceValue = obj;
//根据i的值获取dataProperty,也就是data中的对应ReferenceCollectorData,不过在这里,是对Property进行的读取,有点类似json或者xml的节点
SerializedProperty element = dataProperty.GetArrayElementAtIndex(i);
//对对应节点进行赋值,值为gameobject相对应的fileID
//fileID独一无二,单对单关系,其他挂载在这个gameobject上的script或组件会保存相对应的fileID
element.FindPropertyRelative("gameObject").objectReferenceValue = obj;
}
else
{
dataProperty.InsertArrayElementAtIndex(i);
//等于则说明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);
......@@ -82,7 +100,9 @@ public class ReferenceCollector: MonoBehaviour, ISerializationCallbackReceiver
public void Clear()
{
SerializedObject serializedObject = new SerializedObject(this);
var dataProperty = serializedObject.FindProperty("data");
//根据PropertyPath读取prefab文件中的数据
//如果不知道具体的格式,可以直接右键用文本编辑器打开,搜索data就能找到
var dataProperty = serializedObject.FindProperty("data");
dataProperty.ClearArray();
EditorUtility.SetDirty(this);
serializedObject.ApplyModifiedProperties();
......@@ -98,7 +118,7 @@ public class ReferenceCollector: MonoBehaviour, ISerializationCallbackReceiver
serializedObject.UpdateIfRequiredOrScript();
}
#endif
//使用泛型返回对应key的gameobject
public T Get<T>(string key) where T : class
{
Object dictGo;
......@@ -122,7 +142,7 @@ public class ReferenceCollector: MonoBehaviour, ISerializationCallbackReceiver
public void OnBeforeSerialize()
{
}
//在反序列化后运行
public void OnAfterDeserialize()
{
dict.Clear();
......@@ -134,4 +154,4 @@ public class ReferenceCollector: MonoBehaviour, ISerializationCallbackReceiver
}
}
}
}
\ No newline at end of file
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册