unity inspector 自动装载Commont和Prefab属性

自古美人都是妖i 提交于 2020-02-25 07:45:36

 

在使用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

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!