Search Unity

Do you use tags?

Discussion in 'Scripting' started by Deleted User, Jan 22, 2019.

  1. Deleted User

    Deleted User

    Guest

    I'm curious to what you guys use tags for, if you even use them at all. I don't feel like its efficient to use at all. However, I don't know what else I can use.

    What would you use when, for example, a game is full of boxes, and there is a button to highlight/create/remove them all? Would you findgameobjectwithtag and manipulate these gameobjects or use something else?

    Also, would you use tags to easily locate and differentiate walls or positions of gameobjects in a room? (North/east/south/west)

    If you have any best practices for tagging, I would love to hear about it!
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,537
    Personally I don't use the tags themselves... I have used tag like things (usually as enums or something). But I find Unity's tags a bit limiting (especially since you have to predefine them... why strings if they have to be predefined??? That's a rhetorical question... I know why, it's just stupid).

    This isn't to say they're not used at all by my team. A tag can be used to hack together something in a pinch.

    But at the end of the day... there's almost always a better approach to whatever you're using a tag for.
     
    Antypodish likes this.
  3. SparrowGS

    SparrowGS

    Joined:
    Apr 6, 2017
    Posts:
    2,536
    I rarely use them, and most of the time they are only there in the prototype and are replaced with q custon solution.

    I personally hate the fact it's called a tag and an object can only have one.
    It might be because I'm not native to english but it feels wrong.
     
    User414322, rezuma, jfontius and 2 others like this.
  4. Gladyon

    Gladyon

    Joined:
    Sep 10, 2015
    Posts:
    389
    I do not use Unity tags, mainly because of performance issue (last time I checked they were slow and created some garbage collection).

    Even without talking about the performance issue, they are mostly a 'hack', so it's tempting to use them.
    They are so generic that they can be used for things completely different, which in the end will generate some readability problems in the project.

    It you want something similar to tags for the GameObjects, you can add components (with only data) to them, and if you want some performance when getting all the GOs with a given tag, you can add the objects to a list of objects with the same tag.
    In the end, you can have a dictionary of lists of gameObjects, so that you can get very fast all the objects with a given tag, just be sure to update the dictionary with the Awake() and Destroy() methods properly so that your dictionary is always up to date.
     
    TreeHacks and Kurt-Dekker like this.
  5. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,537
    This is only if you do "obj.tag == MYTAG", use the 'CompareTag' method to avoid GC:
    https://docs.unity3d.com/ScriptReference/Component.CompareTag.html

    The garbage comes from 'tag' having to return a new string when pulling the data from the Unity/C++ side of things.

    The 'name' property has this same issue.
     
  6. Gladyon

    Gladyon

    Joined:
    Sep 10, 2015
    Posts:
    389
    That's good to know.
    I didn't knew that the 'name' property had the problem, I just realized that I avoided the problem by having my own 'Name' for my ScriptableObjects (I suppose that the SO do have the same problem with their 'name' property).
    I did that because at first they weren't SO but plain classes.
    Now I realize that I have been lucky, thanks for the info.
     
    guilindo180821 and CodeBishop like this.
  7. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    I use tags for a few things.
    • I play different footstep sounds when the player is walking depending on what he's walking on. Each tag maps back to a "surface type" that determines what kinds of sounds to play. I went with tags for this, instead of layers, because there is a lot more variety of surface types than layers would support.
    • Similarly, for bullet impact sounds and decals, the surface type a bullet hits determines what kind of sound and decal to use. (cracked glass, concrete, metal, etc).
    • Occasionally I'll check the tags when doing some raycast in cases where the limited number of layers prevents me from being able to have a dedicated layer for all combinations of traits. But I try to avoid that if possible.
    As for your other question of "finding" stuff in your scene, I have various use cases where I need to act on all the stuff in the scene every frame, or every fixed update. Using approaches like FindGameObjectsWithTag or FindObjectsOfType is much too slow for that. Instead, for each object I need to track in this way, I add a component that causes it to register itself with a singleton tracking service on Awake, and to unregister itself on destroy. Then my code can iterate over the arrays in my tracking service rather than finding the objects through Unity's methods. It turns out that this is fairly similar (I believe) to the approach that Hybrid ECS uses to track things performantly in the scene. So, if you're having performance issues due to needing to find and act on lots of stuff in the scene, you might consider Hybrid ECS as an approach.
     
    MartinTilo and Deleted User like this.
  8. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    Two words, endless possibilities - Physics Materials. Actually a lookup between Physics Material and Sound.
    So that's more than two words.



    Tags are near useless and more of a bad practice. Don't use them.
     
  9. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    I use them for lots of things.

    - In OnCollisionEnter using CompareTag I check what kind of object a projectile hits. If it hit a Ship tagged object I do something to the ship, otherwise I don't.

    - My various UI windows sometimes need references to scripts on other UI windows, so I have a base UI object with references that branch out to every other UI window which I just tag with UI for an easy FindWithTag if needed. Though I often go back through my code later and set inspector references instead.

    - I have some use of tags on the client side of my networked game to establish references between objects. This is because objects are instantiated and spawned server side, but on the client side the instantiation of objects is in response to received network messages instead of in a place where object references can be directly cached from the appropriate script.

    The biggest problem with tags is they tend to promote a liberal use of FindGameObjectsWithTag, and that should only be used in one off situations, not every update.
     
  10. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    Thanks. That hadn't occurred to me. I like it.
     
  11. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,742
    I actually prefer OnEnable() to OnDisable() because my feeling is that a disabled Component should not be considered part of a master list of things.

    Getting back to the original question, in lieu of tags I like to use empty MonoBehaviors named appropriately. The ability to hang a bunch of them on any given GameObject gives them far better flexibility than tags.
     
    Kiwasi and LiterallyJeff like this.
  12. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    For gameobjects, I find it's better to check if a gameobject has a component rather than a tag. It's very easy to just make a new component to identify an object at runtime. Hell, you could even make a "Tags" component that can contain multiple string tags, which is already better than Unity's single-tag system.

    In Unreal Engine all actors have a list of tags, which is very useful if one actor needs to be tagged to interact with multiple systems.
     
    Last edited: Jan 22, 2019
  13. Zalosath

    Zalosath

    Joined:
    Sep 13, 2014
    Posts:
    687
    I use tags when I need to perform attacks. I use the Physics#OverlapSphere function, then I use the tag of certain objects to detect if they are enemies or not etc.
     
  14. Munchy2007

    Munchy2007

    Joined:
    Jun 16, 2013
    Posts:
    1,735
    I use tags when it makes sense to do so. Not very often if I'm honest, but there are occasions.
     
  15. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    I use them for quick and dirty prototypes. For anything else, they really don't do the job effectively.

    The one object, one tag limitation is the real killer for me. It effectively means that only one in game system can rely on tags. Every other system must implement a custom solution. And since you are implementing a custom solution anyway, you might as will put everything onto the custom system.

    If I'm doing an information only system (what type of terrain am I walking on? what type of damage do I deal? etc), then I will normally add a component with an enum.

    If I am doing an action system (different objects can all be hit by damage), I tend to use interfaces.

    For finding objects I tend to use a registration system.
     
    TreeHacks, SoulzHD and Kurt-Dekker like this.
  16. gauguerilla

    gauguerilla

    Joined:
    Apr 4, 2023
    Posts:
    2
    I love this and now am wondering (not for the first time): Are Monobehaviours implemented so efficiently that there is not much performance drawback from using them over tags? If so, I think I will adapt that method immediately to distinguish types of objects in my scene.
     
  17. tomfulghum

    tomfulghum

    Joined:
    May 8, 2017
    Posts:
    78
    If a MonoBehaviour doesn't implement any event functions it will basically just happily sit in a list of components and do nothing.
     
    gauguerilla and Kurt-Dekker like this.
  18. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    Its ~72 bytes per MonoBehaviour (might be less in build). Other than that - its pretty much free.

    You can always profile to see the difference of the specific MB by adding multiple of it to the same gameObject each next step in editor. And run a separate script that does something like this:
    Code (CSharp):
    1. Profiler.BeginSample("Test");
    2.  
    3. Instantiate(*thatPrefab*);
    4.  
    5. Profiler.EndSample();
    Then check the GC alloc or memory profiler.
     
    gauguerilla likes this.