If you have ever tried to use tags as a variable input property in a Unity inspector script, you have probably used a regular string property or an array of them.
Then you would be manually typing the tags you want to use in your script, having to double check if they are written correctly and part of the tags that are currently available in your project.
This works just fine but can lead to user input errors and is just plain annoying to use.
Luckily there is a simple solution for this problem!
Using a custom attribute we can visualize our string as a drop-down popup that lists all the available tags, allowing us to select the tag we want and having the selected value automatically assigned to our string.
Using the attribute
In order to use the attribute all you have to do is add the attribute in front of a string or string array property.
using UnityEngine; using System.Collections; public class TagSelectorExample : MonoBehaviour { [TagSelector] public string TagFilter = ""; [TagSelector] public string[] TagFilterArray = new string[] { }; }
Creating the PropertyDrawer
The following code has been based on the TagSelector attribute made by Dylan Engelman (http://jupiterlighthousestudio.com/custom-inspectors-unity/).
I have made some adjustments to extend the use of the attribute and make it easier to extend upon.
Just as with the Hiding or Disabling inspector properties using PropertyDrawers within Unity 5 article, the TagSelectorPropertyDrawer script needs to be placed inside of an editor folder within the project.
The attribute itself can be placed anywhere but it is advised to keep the source file for this next to the Editor folder that contains the drawer.
TagSelector Attribute
using UnityEngine; public class TagSelectorAttribute : PropertyAttribute { public bool UseDefaultTagFieldDrawer = false; }
TagSelectorPropertyDrawer
using UnityEngine; using UnityEditor; using System.Collections.Generic; //Original by DYLAN ENGELMAN http://jupiterlighthousestudio.com/custom-inspectors-unity/ //Altered by Brecht Lecluyse https://www.brechtos.com [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.UseDefaultTagFieldDrawer) { property.stringValue = EditorGUI.TagField(position, label, property.stringValue); } else { //generate the taglist + custom tags List<string> tagList = new List<string>(); tagList.Add("<NoTag>"); tagList.AddRange(UnityEditorInternal.InternalEditorUtility.tags); string propertyString = property.stringValue; int index = -1; if(propertyString =="") { //The tag is empty index = 0; //first index is the special <notag> entry } else { //check if there is an entry that matches the entry and get the index //we skip index 0 as that is a special custom case for (int i = 1; i < tagList.Count; i++) { if (tagList[i] == propertyString) { index = i; break; } } } //Draw the popup box with the current selected index index = EditorGUI.Popup(position, label.text, index, tagList.ToArray()); //Adjust the actual string value of the property based on the selection if(index==0) { property.stringValue = ""; } else if (index >= 1) { property.stringValue = tagList[index]; } else { property.stringValue = ""; } } EditorGUI.EndProperty(); } else { EditorGUI.PropertyField(position, property, label); } } }
And that’s all there is to it. I hope this will be of use to some of you :).
-Brecht
Very helpful; just what I was looking for.
“Warning: count(): Parameter must be an array or an object that implements Countable”
Just an FYI to new coders, to get a count in a list vs. array :
List : use Count;
for
object[] : use List;
I can’t understand what the custom drawer adds to the default one. I mean, I can see the custom use, but it’s the same that Untagged default behaviour. I can only figure out potential problems when comparing Untagged with Untagged and getting true, but it’s such an easily avoidable fail IMHO.
Thanks!
This is an attribute implementation that matches the behavior of the default one. (because that is also what I want)
Only difference is, for this you don’t need a custom editor script for your component if you just want to have string that you want to use as a tag field. Just add the attribute to the property and done.
Unless I’m misunderstanding your comment?
Seems like you have some repeated lines at the beginning of TagSelectorPropertyDrawer
Fixed. Probably a copy paste whoopsy 🙂
When I build game with this script to IOS, then I have cs0246 error
Help! This doesn’t work on Unity 2019.1.1f1 🙁 The override method for DrawProperty() on TagSelectorPropertyDrawer is missing.
Hey Ren.
Not sure why you would need the DrawProperty() override method. As far as I can tell that method is nowhere referenced in the scripts… .
Or am I missing something?
I’ve been using the script without issues in Unity 2017,2018 and 2019
Why propertyDrawer need be in a folder called editor? Do I need create this folder?
Hi Marcio,
They need to be inside a folder called editor for Unity to be able to use the editor features + property drawers are an editor only feature so you don’t want these in your actual game.
Remember that you can have multiple editor folders in you project without any problems.
You can find more info here: https://docs.unity3d.com/Manual/SpecialFolders.html
How do I use this if my script trying to use “[TagSelector]” is outside of the Editor folder? I would like to be able to use this on any of my RunTime scripts for convience. Thank you!
You can use the TagSelector attribute anywhere in the project. But the code itself for the attribute needs to be placed inside of an Editor folder as with all Unity editor code.
I hope this makes sense and answers your question? 🙂
Awful.
Where do I even put the TagSelector Attribute code?
Sad to hear that you find this article Awful.
But to answer your question, here is an excerpt of from the article above.
Following the link will also bring you to a similar tutorial that also has a small image that visually shows you where everything should be placed. The attribute can be placed anywhere in the project.
Should that not solve your issue you can still find all the information on how to create custom attributes and property drawers at the following Unity documentation website: https://docs.unity3d.com/ScriptReference/PropertyDrawer.html
Have a nice day.
To avoid any further confusion I have added a small addition to the article that should make it more clear.
Nah man, great article. That guy just a douche.
Thanks for the great useful addition!
But line 4 and 12 are still the same. For correct work, Unity doesn’t need line 4 ( first mentions of:[CustomPropertyDrawer(typeof(TagSelectorAttribute))]
That is correct. This is actually a copy paste error on my end 🙂
Should be fixed now.
Very useful. Much appreciated! Worked great in 2020.1
Hi, I’m using this on unity 2020, but the autocompletion doesn’t appear and the console shows this error:
The type or namespace name ‘TagSelectorAttribute’ could not be found (are you missing a using directive or an assembly reference?)
Do you know what might be the cause?
Make sure that the TagSelectorPropertyDrawer is inside an editor folder and the TagSelectorAttribute isn’t.
Hi Brechtos,
Great work and thanks for sharing. 🙂
I’ve read your disclaimer at the bottom of the webpage here, but I’d like to ask regardless. Would you mind if I used this code to assist with our workflow on a commercial product I’m working on? Just for clarification, it is a game and we’re not looking to publish any sort of tools with the code you’ve provided.
Cheers!
Thank you, it was great
I cant seem to make this work. I have the editor folder. When i try to use [TagSelector] it doesnt recognize it as a valid property.
Quick note: Cinemachine has a [TagField] property drawer built in which can be useful if you’re using it.
Indeed. This solution was made before Cinemachine even was a thing and ofcourse in case you don’t use Cinemachine. I’m just glad they didn’t use the same name for the attribute name as we use both in our projects 🙂
Hello! I’m an aspiring game developer going into my final year of college this fall. I used this code in a system I developed for a semester long game project, as it was my first time diving into custom editor functionality. The system I made was well received by my other team members, and I’m now starting on the process of retooling that system to be a more generally usable tool that could potentially be released on the asset store. In light of all that, I wanted to ask if including it as a part of my package would be okay. I would, of course, leave the comment crediting you as it is.
Additionally, I’d likely be trying to adapt this code to make essentially the same thing but able to use lists other than just the tags. The ability to make things into dropdown menus is just really nice.
Either way, thanks for sharing your knowledge!