Search Unity

Create tags and layers in the editor using script both edit and runtime modes.

Discussion in 'Assets and Asset Store' started by DubiDuboni, Aug 22, 2019.

  1. DubiDuboni

    DubiDuboni

    Joined:
    Feb 5, 2019
    Posts:
    131
    Code (csharp):
    1.  
    2. using UnityEditor;
    3. using UnityEngine;
    4. using System.Collections;
    5.  
    6. public class TagsAndLayers : MonoBehaviour
    7. {
    8.     private static int maxTags = 10000;
    9.     private static int maxLayers = 31;
    10.  
    11.     /// <summary>
    12.     /// Adds the tag.
    13.     /// </summary>
    14.     /// <returns><c>true</c>, if tag was added, <c>false</c> otherwise.</returns>
    15.     /// <param name="tagName">Tag name.</param>
    16.     public static bool CreateTag(string tagName)
    17.     {
    18.         // Open tag manager
    19.         SerializedObject tagManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/TagManager.asset")[0]);
    20.         // Tags Property
    21.         SerializedProperty tagsProp = tagManager.FindProperty("tags");
    22.         if (tagsProp.arraySize >= maxTags)
    23.         {
    24.             Debug.Log("No more tags can be added to the Tags property. You have " + tagsProp.arraySize + " tags");
    25.             return false;
    26.         }
    27.         // if not found, add it
    28.         if (!PropertyExists(tagsProp, 0, tagsProp.arraySize, tagName))
    29.         {
    30.             int index = tagsProp.arraySize;
    31.             // Insert new array element
    32.             tagsProp.InsertArrayElementAtIndex(index);
    33.             SerializedProperty sp = tagsProp.GetArrayElementAtIndex(index);
    34.             // Set array element to tagName
    35.             sp.stringValue = tagName;
    36.             Debug.Log("Tag: " + tagName + " has been added");
    37.             // Save settings
    38.             tagManager.ApplyModifiedProperties();
    39.  
    40.             return true;
    41.         }
    42.         else
    43.         {
    44.             //Debug.Log ("Tag: " + tagName + " already exists");
    45.         }
    46.         return false;
    47.     }
    48.  
    49.     public static string NewTag(string name)
    50.     {
    51.         CreateTag(name);
    52.  
    53.         if (name == null || name == "")
    54.         {
    55.             name = "Untagged";
    56.         }
    57.  
    58.         return name;
    59.     }
    60.  
    61.     /// <summary>
    62.     /// Removes the tag.
    63.     /// </summary>
    64.     /// <returns><c>true</c>, if tag was removed, <c>false</c> otherwise.</returns>
    65.     /// <param name="tagName">Tag name.</param>
    66.     ///
    67.     public static bool RemoveTag(string tagName)
    68.     {
    69.  
    70.         // Open tag manager
    71.         SerializedObject tagManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/TagManager.asset")[0]);
    72.  
    73.         // Tags Property
    74.         SerializedProperty tagsProp = tagManager.FindProperty("tags");
    75.  
    76.         if (PropertyExists(tagsProp, 0, tagsProp.arraySize, tagName))
    77.         {
    78.             SerializedProperty sp;
    79.  
    80.             for (int i = 0, j = tagsProp.arraySize; i < j; i++)
    81.             {
    82.  
    83.                 sp = tagsProp.GetArrayElementAtIndex(i);
    84.                 if (sp.stringValue == tagName)
    85.                 {
    86.                     tagsProp.DeleteArrayElementAtIndex(i);
    87.                     Debug.Log("Tag: " + tagName + " has been removed");
    88.                     // Save settings
    89.                     tagManager.ApplyModifiedProperties();
    90.                     return true;
    91.                 }
    92.  
    93.             }
    94.         }
    95.  
    96.         return false;
    97.  
    98.     }
    99.  
    100.     /// <summary>
    101.     /// Checks to see if tag exists.
    102.     /// </summary>
    103.     /// <returns><c>true</c>, if tag exists, <c>false</c> otherwise.</returns>
    104.     /// <param name="tagName">Tag name.</param>
    105.     public static bool TagExists(string tagName)
    106.     {
    107.         // Open tag manager
    108.         SerializedObject tagManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/TagManager.asset")[0]);
    109.  
    110.         // Layers Property
    111.         SerializedProperty tagsProp = tagManager.FindProperty("tags");
    112.         return PropertyExists(tagsProp, 0, maxTags, tagName);
    113.     }
    114.     /// <summary>
    115.     /// Adds the layer.
    116.     /// </summary>
    117.     /// <returns><c>true</c>, if layer was added, <c>false</c> otherwise.</returns>
    118.     /// <param name="layerName">Layer name.</param>
    119.     public static bool CreateLayer(string layerName)
    120.     {
    121.         // Open tag manager
    122.         SerializedObject tagManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/TagManager.asset")[0]);
    123.         // Layers Property
    124.         SerializedProperty layersProp = tagManager.FindProperty("layers");
    125.         if (!PropertyExists(layersProp, 0, maxLayers, layerName))
    126.         {
    127.             SerializedProperty sp;
    128.             // Start at layer 9th index -> 8 (zero based) => first 8 reserved for unity / greyed out
    129.             for (int i = 8, j = maxLayers; i < j; i++)
    130.             {
    131.                 sp = layersProp.GetArrayElementAtIndex(i);
    132.                 if (sp.stringValue == "")
    133.                 {
    134.                     // Assign string value to layer
    135.                     sp.stringValue = layerName;
    136.                     Debug.Log("Layer: " + layerName + " has been added");
    137.                     // Save settings
    138.                     tagManager.ApplyModifiedProperties();
    139.                     return true;
    140.                 }
    141.                 if (i == j)
    142.                     Debug.Log("All allowed layers have been filled");
    143.             }
    144.         }
    145.         else
    146.         {
    147.             //Debug.Log ("Layer: " + layerName + " already exists");
    148.         }
    149.         return false;
    150.     }
    151.  
    152.     public static string NewLayer(string name)
    153.     {
    154.         if (name != null || name != "")
    155.         {
    156.             CreateLayer(name);
    157.         }
    158.  
    159.         return name;
    160.     }
    161.  
    162.     /// <summary>
    163.     /// Removes the layer.
    164.     /// </summary>
    165.     /// <returns><c>true</c>, if layer was removed, <c>false</c> otherwise.</returns>
    166.     /// <param name="layerName">Layer name.</param>
    167.     public static bool RemoveLayer(string layerName)
    168.     {
    169.  
    170.         // Open tag manager
    171.         SerializedObject tagManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/TagManager.asset")[0]);
    172.  
    173.         // Tags Property
    174.         SerializedProperty layersProp = tagManager.FindProperty("layers");
    175.  
    176.         if (PropertyExists(layersProp, 0, layersProp.arraySize, layerName))
    177.         {
    178.             SerializedProperty sp;
    179.  
    180.             for (int i = 0, j = layersProp.arraySize; i < j; i++)
    181.             {
    182.  
    183.                 sp = layersProp.GetArrayElementAtIndex(i);
    184.  
    185.                 if (sp.stringValue == layerName)
    186.                 {
    187.                     sp.stringValue = "";
    188.                     Debug.Log("Layer: " + layerName + " has been removed");
    189.                     // Save settings
    190.                     tagManager.ApplyModifiedProperties();
    191.                     return true;
    192.                 }
    193.  
    194.             }
    195.         }
    196.  
    197.         return false;
    198.  
    199.     }
    200.     /// <summary>
    201.     /// Checks to see if layer exists.
    202.     /// </summary>
    203.     /// <returns><c>true</c>, if layer exists, <c>false</c> otherwise.</returns>
    204.     /// <param name="layerName">Layer name.</param>
    205.     public static bool LayerExists(string layerName)
    206.     {
    207.         // Open tag manager
    208.         SerializedObject tagManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/TagManager.asset")[0]);
    209.  
    210.         // Layers Property
    211.         SerializedProperty layersProp = tagManager.FindProperty("layers");
    212.         return PropertyExists(layersProp, 0, maxLayers, layerName);
    213.     }
    214.     /// <summary>
    215.     /// Checks if the value exists in the property.
    216.     /// </summary>
    217.     /// <returns><c>true</c>, if exists was propertyed, <c>false</c> otherwise.</returns>
    218.     /// <param name="property">Property.</param>
    219.     /// <param name="start">Start.</param>
    220.     /// <param name="end">End.</param>
    221.     /// <param name="value">Value.</param>
    222.     private static bool PropertyExists(SerializedProperty property, int start, int end, string value)
    223.     {
    224.         for (int i = start; i < end; i++)
    225.         {
    226.             SerializedProperty t = property.GetArrayElementAtIndex(i);
    227.             if (t.stringValue.Equals(value))
    228.             {
    229.                 return true;
    230.             }
    231.         }
    232.         return false;
    233.     }
    234.  
    235.     public void AddNewTag(string name)
    236.     {
    237.         CreateTag(name);
    238.     }
    239.  
    240.     public void DeleteTag(string name)
    241.     {
    242.         RemoveTag(name);
    243.     }
    244.  
    245.     public void AddNewLayer(string name)
    246.     {
    247.         CreateLayer(name);
    248.     }
    249.  
    250.     public void DeleteLayer(string name)
    251.     {
    252.         RemoveLayer(name);
    253.     }
    254. }
    255.  
    And the editor script must be in Editor folder in the Assets :

    Code (csharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEditor;
    5. using UnityEngine;
    6.  
    7. [CustomEditor(typeof(TagsAndLayers))]
    8. public class TagsAndLayersCustomEditor : Editor
    9. {
    10.     string tagname = "";
    11.     string layername = "";
    12.  
    13.     public override void OnInspectorGUI()
    14.     {
    15.         DrawDefaultInspector();
    16.         TagsAndLayers myTarget = (TagsAndLayers)target;
    17.  
    18.         tagname = EditorGUILayout.TextField("", tagname);
    19.  
    20.         if (tagname == "" || tagname == null)
    21.         {
    22.             GUI.enabled = false;
    23.         }
    24.         else
    25.         {
    26.             GUI.enabled = true;
    27.         }
    28.         if (GUILayout.Button("Create Tag"))
    29.         {
    30.             myTarget.AddNewTag(tagname);
    31.         }
    32.  
    33.         if (GUILayout.Button("Remove Tag"))
    34.         {
    35.             myTarget.DeleteTag(tagname);
    36.         }
    37.  
    38.         GUILayout.Space(50);
    39.  
    40.         layername = EditorGUILayout.TextField("", layername);
    41.  
    42.         if(layername == "" || layername == null)
    43.         {
    44.             GUI.enabled = false;
    45.         }
    46.         else
    47.         {
    48.             GUI.enabled = true;
    49.         }
    50.         if (GUILayout.Button("Create Layer"))
    51.         {
    52.             myTarget.AddNewLayer(layername);
    53.         }
    54.  
    55.         if (GUILayout.Button("Remove Layer"))
    56.         {
    57.             myTarget.DeleteLayer(layername);
    58.         }
    59.     }
    60. }
    61.  
    Use the buttons either in edit mode or runtime to create/remove tags and layers.

    A small test script, You can set a new tag and the tag will be created in the editor :
    Once adding the script to a gameobject it will create a new gameobject tagged already :

    https://cdn1.imggmi.com/uploads/2019/8/22/acbb4500596c0b67b9a23aeb860a13d0-full.jpg

    And the new created object is tagged : "I was here"

    https://cdn1.imggmi.com/uploads/2019/8/22/76905fd9304c966005bbb2f5ecb0213a-full.jpg
     
    Last edited: Aug 22, 2019
  2. Leohd

    Leohd

    Joined:
    Feb 7, 2017
    Posts:
    32
    This is god level coding.
     
  3. RoaBen

    RoaBen

    Joined:
    Feb 13, 2019
    Posts:
    5
    Thank you for sharing mate
     
  4. jpgordon00

    jpgordon00

    Joined:
    Jan 9, 2021
    Posts:
    25
    God level coding. I should worship you, sir.
     
  5. Serge_Billault

    Serge_Billault

    Joined:
    Aug 26, 2014
    Posts:
    190
    Unity already provide a simple statement to add a tag from script, guess... InternalEditorUtility.AddTag();
    I dont know what to say to you and your god...
    Code (CSharp):
    1.  
    2. using System;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5. using UnityEngine;
    6.  
    7. //****************************************************************************
    8.  
    9. #if UNITY_EDITOR
    10.  
    11. using UnityEditorInternal;
    12.  
    13. //****************************************************************************
    14.  
    15. static public class Tags
    16. {
    17.     private const string TAG_MNGR_ASSET = "ProjectSettings/TagManager.asset";
    18.  
    19.     static private void Add( List< string > tags, string tag )
    20.     {
    21.         if( tags == null )                         return;
    22.  
    23.         if( string.IsNullOrEmpty( tag ) ) return;
    24.  
    25.         for( int t = 0, count = tags.Count; t < count; ++t )
    26.         {
    27.             if( tag.Equals( tags[ t ], StringComparison.Ordinal ) ) return;
    28.         }
    29.  
    30.         InternalEditorUtility.AddTag( tag );
    31.  
    32.         tags.Add( tag );
    33.     }
    34.  
    35.     [ UnityEditor.Callbacks.DidReloadScripts ] static public void Create()
    36.     {
    37.         List< string > tags = new List< string >( InternalEditorUtility.tags );
    38.  
    39.         Add( tags, "METAL"  );
    40.  
    41.         Add( tags, "FLESHY" );
    42.     }
    43. }
    44.  
    45. #endif
     
    Pholith and jpgordon00 like this.
  6. ohavitd

    ohavitd

    Joined:
    Nov 1, 2021
    Posts:
    4
    Thx to @Yseron :)

    If you wish to add your favourite tags to your project on editor startup, you can use the unity event for this.

    Code (CSharp):
    1. // E.g. File: Assets/MyProject/Extends/GameObject.cs
    2. public static class GameObjectExtension
    3. {
    4.     public static readonly string[] Tags =
    5.     {
    6.         "SafeArea",
    7.         "UI",
    8.         "Avatar",
    9.         "...",
    10.     };
    11. }
    12.  
    13.  
    14. // E.g. File: Assets/MyProject/Editor/Startup.cs
    15. using System.Linq;
    16. using UnityEditor;
    17. using UnityEditorInternal;
    18.  
    19. namespace MyProject.Editor
    20. {
    21.     [InitializeOnLoad]
    22.     public class Startup
    23.     {
    24.         static Startup()
    25.         {
    26.             foreach (var tag in GameObjectExtension.Tags)
    27.             {
    28.                 if (tag.Length == 0) continue;
    29.                 if (!InternalEditorUtility.tags.Contains(tag))
    30.                 {
    31.                     InternalEditorUtility.AddTag(tag);
    32.                 }
    33.             }
    34.         }
    35.     }
    36. }
     
    gjf likes this.