Subscribe to Jupiter Lighthouse Studio        RSS Feed
-----

Tag Selector & VariantReference Custom Inspector in Unity

Icon Leave Comment
I've been tinkering around with the custom inspectors a lot lately in Unity. Namely PropertyDrawers, which funny enough I have been calling "drawers" to date, as in the drawer of a dresser or bureau. I only this week realized it's 'draw-er', like one who draws. There's a few limitations to PropertyDrawers that I don't like, but for the most part they're damn powerful little things that allow for some interesting things. I'd love to touch on a few drawers I created that perform pretty useful yet generic tasks in Unity.

For starters, for anyone who doesn't know what a PropertyDrawer is, I suggest heading over to the Unity article on the topic. In that article you will find that you can associate a PropertyDrawer directly to a data type. Or you can associate a PropertyDrawer with an attribute, which allows you to loosely couple your PropertyDrawer to any field that is attributed as such. Today I will be covering two simple examples of a PropertyDrawer that are associated directly with a property, and associated with an attribute. Later I'll cover a special type of PropertyDrawers I created as an extension to the PropertyDrawer system that I call PropertyModifiers.

VariantReference

Lets first cover the most simple PropertyDrawer that can be associated with a type directly. Here is a serializable class I create call VariantReference. Sometimes when creating components I have a need to allow the user in the unity designer to associate some extra parameters that may be passed on to something else. Lets say for instance I have a Trigger script that when activated calls the 'Trigger' method on a TriggerableMechanism script I have on another GameObject.

This Trigger method accepts an optional argument of type object, depending on what type of TriggerableMechanism we target. We want the designer to be able to choose the type of object to send, store and serialize that value, and also draw the appropriate property field for that type. A VariantReference allows this by acting as a wrapper around a value of a configurable type, we restrict these types to those that are unique to the unity design process. Now I can just add a field to the Trigger of type VariantReference and store this value there.

Now we need to write up that PropertyDrawer to draw the proper inspector. It will create a drop down box with the available types, as well as a input field to define the value based on the type. So I create the VariantReferencePropertyDrawer to accomplish just this.

Posted Image

Tag Selector

Another common inspector I wanted in the designer for unity was a way to select a tag from a list of tags instead of just a string field. Because tags are stored in strings, I couldn't just make a PropertyDrawer for some 'tag' type. Instead I create an attribute that can be associated with a string that tells the inspector to draw a popup with all the tags as options.

The attribute itself is fairly simple.

 
    [System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)]
    public class TagSelectorAttribute : PropertyAttribute
    {
        public bool AllowUntagged;
    }



And the TagSelectorPropertyDrawer is actually fairly simple as well. I merely use the UnityEditorInternal namespace to get a reference to all the tags, and create a string popup from that. I also allow for 'Untagged' as an option in the attribute which include or excludes it as a choice in the popup. From what I understand the UnityEditorInternal namespace is subject to change, so this 'could' break in the future. But it's such a basic method that a fix should be relatively simple.

using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.Linq;

using com.spacepuppy;

namespace com.spacepuppyeditor.Inspectors
{

    [CustomPropertyDrawer(typeof(TagSelectorAttribute))]
    public class TagSelectorPropertyDrawer : PropertyDrawer
    {

        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            if (property.propertyType == SerializedPropertyType.String)
            {
                EditorGUI.BeginProperty(position, label, property);

                var attrib = this.attribute as TagSelectorAttribute;

                if (attrib.AllowUntagged)
                {
                    property.stringValue = EditorGUI.TagField(position, label, property.stringValue);
                }
                else
                {
                    var tags = (from s in UnityEditorInternal.InternalEditorUtility.tags where s != SPConstants.TAG_UNTAGGED select new GUIContent(s)).ToArray();
                    var stag = property.stringValue;
                    int index = -1;
                    for(int i = 0; i < tags.Length; i++)
                    {
                        if(tags[i].text == stag)
                        {
                            index = i;
                            break;
                        }
                    }
                    index = EditorGUI.Popup(position, label, index, tags);
                    if(index >= 0)
                    {
                        property.stringValue = tags[index].text;
                    }
                    else
                    {
                        property.stringValue = null;
                    }
                }

                EditorGUI.EndProperty();
            }
            else
            {
                EditorGUI.PropertyField(position, property, label);
            }

        }

    }

}



This was a post from Jupiter Lighthouse Studio.
You can find this article and others at: http://jupiterlighth...spectors-unity/

0 Comments On This Entry

 

Trackbacks for this entry [ Trackback URL ]

There are no Trackbacks for this entry

October 2017

S M T W T F S
1234567
891011121314
151617181920 21
22232425262728
293031    

Tags

    Recent Entries

    Search My Blog

    0 user(s) viewing

    0 Guests
    0 member(s)
    0 anonymous member(s)

    Categories