Multiple tags for one GameObject

Hi everyone!
Basically I am trying to create an inventory system for my game. Several tags attached to one object would really help! However it seems that that’s currently not possible in Unity. If so — please advise me on some easy to understand workarounds

I would simply create a custom component which has a list of strings for tags. Then instead of asking for the GameObject.tag you do GetComponent().tags (or similar) to check if the object is tagged this way. You can build upon this and make it very easy to work with via editor scripts (e.g. dropdown lists instead of having to type the tag like the Unity tag system does). You can also use the Unity tag manager to define your tags and get them in an editor script.

If you are using tags for an inventory system, you also don’t have to think about being efficient. Getting a component and searching through a list of objects is not a problem at all. Doing complex operations on thousands of objects is, but these tags are trivial, so don’t worry. :wink:

Here’s some example code:

[111634-customtags.jpg*_|111634]

MonoBehavior###

using UnityEngine;
using System.Collections.Generic;

public class CustomTag : MonoBehaviour 
{
	[SerializeField]
	private List<string> tags = new List<string>();
	
	public bool HasTag(string tag)
	{
		return tags.Contains(tag);
	}
	
	public IEnumerable<string> GetTags()
	{
		return tags;
	}
	
	public void Rename(int index, string tagName)
	{
		tags[index] = tagName;
	}
	
	public string GetAtIndex(int index)
	{
		return tags[index];
	}
	
	public int Count
	{
		get { return tags.Count; }
	}
}

Custom Editor

using UnityEditor;
using UnityEngine;
using UnityEditorInternal;

[CustomEditor(typeof(CustomTag))]
public class CustomTagEditor : Editor
{
	private string[] unityTags;
	SerializedProperty tagsProp;
	private ReorderableList list;

	private void OnEnable()
	{
		unityTags = InternalEditorUtility.tags;
		tagsProp = serializedObject.FindProperty("tags");
		list = new ReorderableList(serializedObject, tagsProp, true, true, true, true);
		list.drawHeaderCallback += DrawHeader;
		list.drawElementCallback += DrawElement;
		list.onAddDropdownCallback += OnAddDropdown;
	}

	private void DrawHeader(Rect rect)
	{
		EditorGUI.LabelField(rect, new GUIContent("Tags"), EditorStyles.boldLabel);
	}

	private void DrawElement(Rect rect, int index, bool isActive, bool isFocused)
	{
		var element = list.serializedProperty.GetArrayElementAtIndex(index);
		rect.y += 2;
		EditorGUI.LabelField(rect, element.stringValue);
	}

	private void OnAddDropdown(Rect buttonRect, ReorderableList list)
	{
		GenericMenu menu = new GenericMenu();

		for (int i = 0; i < unityTags.Length; i++)
		{
			var label = new GUIContent(unityTags*);*
  •  	// Don't allow duplicate tags to be added.*
    

_ if (PropertyContainsString(tagsProp, unityTags*))_
_
menu.AddDisabledItem(label);_
_
else*_
_ menu.AddItem(label, false, OnAddClickHandler, unityTags*);
}*_

* menu.ShowAsContext();*
* }*

* private bool PropertyContainsString(SerializedProperty property, string value)*
* {*
* if (property.isArray)*
* {*
* for (int i = 0; i < property.arraySize; i++)*
* {*
* if (property.GetArrayElementAtIndex(i).stringValue == value)*
* return true;*
* }*
* }*
* else*
* return property.stringValue == value;*

* return false;*
* }*

* private void OnAddClickHandler(object tag)*
* {*
* int index = list.serializedProperty.arraySize;*
* list.serializedProperty.arraySize++;*
* list.index = index;*

* var element = list.serializedProperty.GetArrayElementAtIndex(index);*
* element.stringValue = (string)tag;*
* serializedObject.ApplyModifiedProperties();*
* }*

* public override void OnInspectorGUI()*
* {*
* GUILayout.Space(6);*
* serializedObject.Update();*
* list.DoLayoutList();*
* serializedObject.ApplyModifiedProperties();*
* GUILayout.Space(3);*
* }*
}

*
So, to use the example, you would call GetComponent().HasTag(“Player”) to check if the custom tags list contains the player tag.
PS: This answer shows how to implement a custom script that provides multiple tags per GameObject. There may be reasons for using such a system, but in general, I wouldn’t recommend this for use as the base of an inventory system. In my idea, multiple tags would make sense if certain environment objects are tagged by designer and runtime scripts with multiple properties within a complex AI or quest scenario. For example, if the player picks up a knife from the counter, it gets the tag “TouchedByPlayer” and then the detective will accuse the player of being a suspect. And now there are many more tags like “HasBloodStains” etc which are all used by the narrative and quest system of the game._

For anything even slightly complicated, throw away tags and use a script. Let the variables do all the work of tags. For example:

class inventoryItem : MonoBehavior {
  public string name;
  public int itemNum;
  ...
}

Then you can use GetComponent<inventoryItem>() and examine those variables. Then you’ll naturally start to add some functions.

There are Unity Assets for multiple tags. I’d check them out if you’re really interested. Besides that, you can use inheritance if that’s what you’re thinking about. Is it something like, a sword is an item, a weapon, and a sword. Is that what you’re trying to do?