ReferenceCollectorEditor.cs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEditor;
  4. using UnityEngine;
  5. //Object并非C#基础中的Object,而是 UnityEngine.Object
  6. using Object = UnityEngine.Object;
  7. //自定义ReferenceCollector类在界面中的显示与功能
  8. [CustomEditor(typeof (ReferenceCollector))]
  9. public class ReferenceCollectorEditor: Editor
  10. {
  11. //输入在textfield中的字符串
  12. private string searchKey
  13. {
  14. get
  15. {
  16. return _searchKey;
  17. }
  18. set
  19. {
  20. if (_searchKey != value)
  21. {
  22. _searchKey = value;
  23. heroPrefab = referenceCollector.Get<Object>(searchKey);
  24. }
  25. }
  26. }
  27. private ReferenceCollector referenceCollector;
  28. private Object heroPrefab;
  29. private string _searchKey = "";
  30. private void DelNullReference()
  31. {
  32. var dataProperty = serializedObject.FindProperty("data");
  33. for (int i = dataProperty.arraySize - 1; i >= 0; i--)
  34. {
  35. var gameObjectProperty = dataProperty.GetArrayElementAtIndex(i).FindPropertyRelative("gameObject");
  36. if (gameObjectProperty.objectReferenceValue == null)
  37. {
  38. dataProperty.DeleteArrayElementAtIndex(i);
  39. EditorUtility.SetDirty(referenceCollector);
  40. serializedObject.ApplyModifiedProperties();
  41. serializedObject.UpdateIfRequiredOrScript();
  42. }
  43. }
  44. }
  45. private void OnEnable()
  46. {
  47. //将被选中的gameobject所挂载的ReferenceCollector赋值给编辑器类中的ReferenceCollector,方便操作
  48. referenceCollector = (ReferenceCollector) target;
  49. }
  50. public override void OnInspectorGUI()
  51. {
  52. //使ReferenceCollector支持撤销操作,还有Redo,不过没有在这里使用
  53. Undo.RecordObject(referenceCollector, "Changed Settings");
  54. var dataProperty = serializedObject.FindProperty("data");
  55. //开始水平布局,如果是比较新版本学习U3D的,可能不知道这东西,这个是老GUI系统的知识,除了用在编辑器里,还可以用在生成的游戏中
  56. GUILayout.BeginHorizontal();
  57. //下面几个if都是点击按钮就会返回true调用里面的东西
  58. if (GUILayout.Button("添加引用"))
  59. {
  60. //添加新的元素,具体的函数注释
  61. // Guid.NewGuid().GetHashCode().ToString() 就是新建后默认的key
  62. AddReference(dataProperty, Guid.NewGuid().GetHashCode().ToString(), null);
  63. }
  64. if (GUILayout.Button("全部删除"))
  65. {
  66. referenceCollector.Clear();
  67. }
  68. if (GUILayout.Button("删除空引用"))
  69. {
  70. DelNullReference();
  71. }
  72. if (GUILayout.Button("排序"))
  73. {
  74. referenceCollector.Sort();
  75. }
  76. EditorGUILayout.EndHorizontal();
  77. EditorGUILayout.BeginHorizontal();
  78. //可以在编辑器中对searchKey进行赋值,只要输入对应的Key值,就可以点后面的删除按钮删除相对应的元素
  79. searchKey = EditorGUILayout.TextField(searchKey);
  80. //添加的可以用于选中Object的框,这里的object也是(UnityEngine.Object
  81. //第三个参数为是否只能引用scene中的Object
  82. EditorGUILayout.ObjectField(heroPrefab, typeof (Object), false);
  83. if (GUILayout.Button("删除"))
  84. {
  85. referenceCollector.Remove(searchKey);
  86. heroPrefab = null;
  87. }
  88. GUILayout.EndHorizontal();
  89. EditorGUILayout.Space();
  90. var delList = new List<int>();
  91. SerializedProperty property;
  92. //遍历ReferenceCollector中data list的所有元素,显示在编辑器中
  93. for (int i = referenceCollector.data.Count - 1; i >= 0; i--)
  94. {
  95. GUILayout.BeginHorizontal();
  96. //这里的知识点在ReferenceCollector中有说
  97. property = dataProperty.GetArrayElementAtIndex(i).FindPropertyRelative("key");
  98. property.stringValue = EditorGUILayout.TextField(property.stringValue, GUILayout.Width(150));
  99. property = dataProperty.GetArrayElementAtIndex(i).FindPropertyRelative("gameObject");
  100. property.objectReferenceValue = EditorGUILayout.ObjectField(property.objectReferenceValue, typeof(Object), true);
  101. if (GUILayout.Button("X"))
  102. {
  103. //将元素添加进删除list
  104. delList.Add(i);
  105. }
  106. GUILayout.EndHorizontal();
  107. }
  108. var eventType = Event.current.type;
  109. //在Inspector 窗口上创建区域,向区域拖拽资源对象,获取到拖拽到区域的对象
  110. if (eventType == EventType.DragUpdated || eventType == EventType.DragPerform)
  111. {
  112. // Show a copy icon on the drag
  113. DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
  114. if (eventType == EventType.DragPerform)
  115. {
  116. DragAndDrop.AcceptDrag();
  117. foreach (var o in DragAndDrop.objectReferences)
  118. {
  119. AddReference(dataProperty, o.name, o);
  120. }
  121. }
  122. Event.current.Use();
  123. }
  124. //遍历删除list,将其删除掉
  125. foreach (var i in delList)
  126. {
  127. dataProperty.DeleteArrayElementAtIndex(i);
  128. }
  129. serializedObject.ApplyModifiedProperties();
  130. serializedObject.UpdateIfRequiredOrScript();
  131. }
  132. //添加元素,具体知识点在ReferenceCollector中说了
  133. private void AddReference(SerializedProperty dataProperty, string key, Object obj)
  134. {
  135. int index = dataProperty.arraySize;
  136. dataProperty.InsertArrayElementAtIndex(index);
  137. var element = dataProperty.GetArrayElementAtIndex(index);
  138. element.FindPropertyRelative("key").stringValue = key;
  139. element.FindPropertyRelative("gameObject").objectReferenceValue = obj;
  140. }
  141. }