Unity3D Inspector 序列化属性自动赋值

做UI的时候,序列化的属性,代码写好后,每次都需要手动拖动相应的GameObject到Inspector上。通过下面的方法,我们可以实现自动赋值,省去手动拖动的体力劳动。

效果如下,序列化的属性的 变量名 跟 子物体的名称保持一致,比如下图中的 _weapon 和 _bag .

Kapture 2019-04-08.gif

实现如下:
创建脚本 AutohookAttribute.cs

     // NOTE DONT put in an editor folder!
    using UnityEngine;

    public class AutohookAttribute : PropertyAttribute
    {
    }

创建Editor文件夹,并在里面创建 AutohookPropertyDrawer.cs

// NOTE put in a Editor folder
using UnityEditor;
using UnityEngine;

[CustomPropertyDrawer(typeof(AutohookAttribute))]
public class AutohookPropertyDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
          var component = FindAutohookTarget(property);
          if (component != null)
          {
         //  if (property.objectReferenceValue == null)
              property.objectReferenceValue = component;
           }
      EditorGUI.PropertyField(position, property, label);
    }


/// 
/// Takes a SerializedProperty and finds a local component that can be slotted into it.
/// Local in this context means its a component attached to the same GameObject.
/// This could easily be changed to use GetComponentInParent/GetComponentInChildren
/// 
/// 
/// 
    private Component FindAutohookTarget(SerializedProperty property)
   {
    var root = property.serializedObject;

    if (root.targetObject is Component)
    {
        // first, lets find the type of component were trying to autohook...
        var type = GetTypeFromProperty(property);
        
        // ...then use GetComponent(type) to see if there is one on our object.
        var component = (Component)root.targetObject;
       //  var gb = (GameObject) root.targetObject;
       //  Debug.LogError(component.transform(type));
        var components = component.GetComponentsInChildren(type);
        foreach (var item in components)
        {
            //确保GameObject不要有重名的
            if (item.gameObject.name == property.name)
            {
                return item.gameObject.GetComponent(type);
            }
        }
    }
    else
    {
        Debug.Log("OH NO handle fails here better pls");
    }

    return null;
  }

/// 
/// Uses reflection to get the type from a serialized property
/// 
/// 
/// 
    private static System.Type GetTypeFromProperty(SerializedProperty property)
    {
    // first, lets get the Type of component this serialized property is part of...
    var parentComponentType = property.serializedObject.targetObject.GetType();
    // ... then, using reflection well get the raw field info of the property this
    // SerializedProperty represents...
    var fieldInfo = parentComponentType.GetField(property.propertyPath);
    // ... using that we can return the raw .net type!
    return fieldInfo.FieldType;
   }
}

测试脚本:

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;

 public class Test : MonoBehaviour
 {

    [Autohook]
    public Transform _weapon;

    [Autohook]
    public Transform _bag;
    
    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        
     }
  }

参考:https://gist.github.com/LotteMakesStuff/d6a9a4944fc667e557083108606b7d22

你可能感兴趣的:(Unity3D Inspector 序列化属性自动赋值)