在使用unity的过程中,经常遇到这样的问题:每次都需要手动为序列化属性。像这样:

试着找了找,真的找到了一份代码,但是缺少自动装载Prefab的功能。之后我花了点时间添加这个功能。
使用方法:
1 [Autohook] 2 public Button SendBtn; 3 [Autohook] 4 public Button StartBtn; 5 [Autohook] 6 public Button LeaveBtn; 7 [Autohook] 8 public Text RoomDateText; 9 [Autohook] 10 public ScrollRect PlayerList; 11 12 [Autohook(AutohookAttribute.HookType.Prefab)] 13 public GameObject PlayerBarPrefab; 14 [Autohook(AutohookAttribute.HookType.Prefab)] 15 public GameObject RoomBarPrefab;
下面是源文件:

1 // NOTE DONT put in an editor folder!
2 using UnityEngine;
3
4 /// <summary>
5 /// use [Autohook] to modify Component
6 /// use [Autohook(AutohookAttribute.HookType.Prefab)] to modify Prefab
7 /// </summary>
8 public class AutohookAttribute : PropertyAttribute
9 {
10 public readonly HookType hookType;
11 public readonly string prefabPath;
12
13 public enum HookType {
14 Component,
15 Prefab
16 }
17
18 public AutohookAttribute(HookType hookType = HookType.Component, string prefabPath = "Assets/Prefabs")
19 {
20 this.hookType = hookType;
21 this.prefabPath = prefabPath;
22 }
23 }

1 // NOTE put in a Editor folder
2 using UnityEditor;
3 using UnityEngine;
4 using UnityEngine.Assertions;
5
6 [CustomPropertyDrawer(typeof(AutohookAttribute))]
7 public class AutohookPropertyDrawer : PropertyDrawer
8 {
9 public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
10 {
11 if (property.objectReferenceValue != null)
12 {
13 EditorGUI.PropertyField(position, property, label);
14 return;
15 }
16 AutohookAttribute autohookAttribute = (AutohookAttribute)attribute;
17 if (autohookAttribute.hookType == AutohookAttribute.HookType.Component)
18 {
19 //Assert.IsFalse(GetTypeFromProperty(property).Equals(typeof(GameObject)),
20 // "use [Autohook] to modify "+property.name);
21 var component = FindAutohookTarget(property);
22 if (component != null)
23 {
24 // if (property.objectReferenceValue == null)
25 property.objectReferenceValue = component;
26 }
27 } else if (autohookAttribute.hookType == AutohookAttribute.HookType.Prefab)
28 {
29 //Assert.IsTrue(GetTypeFromProperty(property).Equals(typeof(GameObject)),
30 // "use [Autohook(AutohookAttribute.HookType.Prefab)] to modify " + property.name);
31 string name = property.name;
32 if (name.EndsWith("Prefab"))
33 {
34 name = name.Remove(name.Length - 6);
35 }
36 var prefab = FindPrefab(property, name, autohookAttribute.prefabPath);
37 if (prefab != null)
38 {
39 property.objectReferenceValue = prefab;
40 }
41 }
42
43
44 EditorGUI.PropertyField(position, property, label);
45 }
46
47 private GameObject FindPrefab(SerializedProperty property, string name, string assertPath)
48 {
49 string[] guids = AssetDatabase.FindAssets("t:Prefab", new string[] { assertPath });
50 foreach (string guid in guids)
51 {
52 string path = AssetDatabase.GUIDToAssetPath(guid);
53 string prefabName = System.IO.Path.GetFileNameWithoutExtension(path);
54 if (name == prefabName)
55 {
56 return AssetDatabase.LoadAssetAtPath<GameObject>(path);
57 }
58 }
59 return null;
60 }
61
62 /// <summary>
63 /// Takes a SerializedProperty and finds a local component that can be slotted into it.
64 /// Local in this context means its a component attached to the same GameObject.
65 /// This could easily be changed to use GetComponentInParent/GetComponentInChildren
66 /// </summary>
67 /// <param name="property"></param>
68 /// <returns></returns>
69 private Component FindAutohookTarget(SerializedProperty property)
70 {
71
72 var root = property.serializedObject;
73
74 if (root.targetObject is Component)
75 {
76 // first, lets find the type of component were trying to autohook...
77 var type = GetTypeFromProperty(property);
78
79 // ...then use GetComponent(type) to see if there is one on our object.
80 var component = (Component)root.targetObject;
81 // var gb = (GameObject) root.targetObject;
82 // Debug.LogError(component.transform(type));
83 var components = component.GetComponentsInChildren(type);
84 foreach (var item in components)
85 {
86 //确保GameObject不要有重名的
87 if (item.gameObject.name == property.name)
88 {
89 return item.gameObject.GetComponent(type);
90 }
91 }
92 }
93 else
94 {
95 Debug.Log("OH NO handle fails here better pls");
96 }
97
98 return null;
99 }
100
101 /// <summary>
102 /// Uses reflection to get the type from a serialized property
103 /// </summary>
104 /// <param name="property"></param>
105 /// <returns></returns>
106 private static System.Type GetTypeFromProperty(SerializedProperty property)
107 {
108 // first, lets get the Type of component this serialized property is part of...
109 var parentComponentType = property.serializedObject.targetObject.GetType();
110 // ... then, using reflection well get the raw field info of the property this
111 // SerializedProperty represents...
112 var fieldInfo = parentComponentType.GetField(property.propertyPath);
113 // ... using that we can return the raw .net type!
114 return fieldInfo.FieldType;
115 }
116 }
来源:https://www.cnblogs.com/backinfile/p/12359861.html
