在使用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 }
AutohookAttribute.cs
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 }
AutohookPropertyDrawer.cs
原文地址:https://www.cnblogs.com/backinfile/p/12359861.html
时间: 2024-10-13 17:37:22