- Home /
Is CompareTag better than gameObject.tag performance wise?
Hello,
Someone told me that this:
function OnTriggerEnter (other : Collider) {
var deathMenu = GetComponent("");
if (other.CompareTag("Lava")) {
}
}
Is better than this:
function OnTriggerEnter (other : Collider) {
var deathMenu = GetComponent("");
if (other.tag == "Lava") {
}
}
Is that true? Thanks.
You may want to consider accepting the answer that explains that CompareTag does not cause memory allocations - it's a very important difference that was missed in the previously accepted answer.
Answer by aldonaletto · Jan 01, 2012 at 05:19 PM
CompareTag compiles to fewer CIL instructions than the direct comparison, for sure: it probably results in a single call to the CompareTag internal function, while the other alternative will need a call to the tag getter function (to get the tag string) and another call to the string comparison function, all of this in CIL (the interpreted language used in .NET applications). Since the tag string must be returned by the getter function, space must be allocated, what takes extra time.
Anyway, the difference probably is very small, but may become significant if a lot of CompareTags is used in Update or OnCollision/TriggerStay, and/or the target machine is a mobile device.
So, why would someone ever use '.tag' other than to use the result in a switch statement?
You might use obj1.CompareTag(obj2.tag) (obviously not appropriate for checking for equality, but useful for type matching).
Do you have any insight on the inner workings of CompareTag? Isn't it possible to have the == operator overloaded for this case?
Maybe Aldonaletto wasn't specific enough. Of course you have fewer CIL instructions since you only call a native method from the Unity engine. However on the native C++ side it still has to do a string comparison. That might be a little faster than doing it on the managed side. The real advantage is that the tag value, which is stored on the native side, doesn't have to be allocated on the managed side. I did a test and it looks like a tag value with 4 characters needs 34 bytes while a tag with 6 characters needs 36 bytes. So there seems to be a 30 byte overhead in addition to the actual ASCII string. Strangely a tag with 14 characters requires 54 bytes, so 10 more (40 + 14)
CompareTag goes the otherway round. It passes the string you want to compare your tag to as reference / pointer to the native side. There they can simply compare the tags without any memory allocation.
I'm not sure in which way you want to overload the == operator... The == operator is always based on the type you're comparing in our case the "string" type. Overloading the operator doesn't make much sense here and i don't see how you could avoid the garbage allocation.
Now I'm starting to get it, thanks! Still, it seems a little bit inelegant to have a separate function to compare things.
This answer actually misses the point, as can be seen in the answer below: tag allocates memory, CompareTag does not. On mobile and in VR, this can make a huge difference because we usually try to get to zero allocations because garbage collection creates very noticeable hiccups. Even on a flatscreen desktop game this may be noticeable - but especially in VR, framedrops caused by garbage collection can cause nausea for certain people.
So ... never ever use tag == "sss" - always use CompareTag (there's no benefit, so it's best to make it a habit).
Answer by leoszeto · Sep 14, 2016 at 03:11 AM
The key difference between tag and compareTag is that compareTag does not result in a heap allocation. In Unity, retrieving strings from game Objects will create a duplicate of the string, which will need to be garbage collected.
The source I found reports a ~27% increase in performance of compareTag(aString) vs. using gameObject.tag == "aString";
Source: Unity 5 Game Optimization by Chris Dickinson
Answer by FiveFingerStudios · Jun 10, 2017 at 06:50 AM
One other big item no one else mentioned.
CompareTag check to see if the tag actually exists and Unity will throw an error if it doesn't. Just comparing string won't do that.
Since the question got already bumped.
That's actually also a negative point for the == comparison as well. Getting an error is actually a good thing here. If the tag has not been created in the tag manager you can't use the tag at all. So there would be absolutely no point in comparing tag with a string that can never be a tag. This can easily happen when you mistype the tag in the string so your error is not detected. CompareTag throws an error (or warning) so you know what you did there just makes no sense.
Lots of people seem to fear errors or warnings. Errors are there to actually help you ^^
Answer by MerryYellow · Sep 06, 2018 at 05:17 PM
Operator comparison will create one more string object, which is to be deleted very soon and that makes it generation 0 on the heap. Microsoft claims garbage collector is blazingly fast on gen0 for .NET Framework, but I don't know the situation for Mono.
As a veteran software developer I would recommend ignoring such micro optimizations unless it is called more than a hundred times per frame. I think such optimizations are in the category of compiler optimizations.
Now time for shameless marketing :) Code Enchanter automatically converts all of your tag operator comparisons to method comparisons from your source code.
For example myObject.tag == "myTag" to myObject.CompareTag("myTag")
It has some other performance tricks as well, it's available on http://u3d.as/1d4v
This does not answer the question. This is a pure advertisement post.
The description of your tool is rather generic and doesn't really summarize in detail what this tool actually does and how many features it has. From the screenshots it seems the only things it can do is to comment out empty Unity callbacks, replace == tag comparison with CompareTag and replace a foreach loop with a for loop (which is pretty pointless for arrays and only would make $$anonymous$$or sense for Lists). I'm even wondering how it treats actual IEnumerables.
You really should update your description with actual details about the feature set otherwise those $20 are not really justified.
ps you seem to use quite a few third party libraries. Are you sure you have a distribution right for all of them and that you included all licenses required? Buildalyzer is released under $$anonymous$$IT license so it can be shipped without any issues but the license information has to be shipped as well.
Answer by SUfIaNAHMAD_ · Jan 03, 2021 at 04:08 AM
//
// Summary:
// The tag of this game object.
public string tag { get; set; }
//
// Summary:
// Is this game object tagged with the tag?
//
// Parameters:
// tag:
// The tag to compare.
[FreeFunction(Name = "GameObjectBindings::CompareTag", HasExplicitThis = true)]
public bool CompareTag(string tag);
Note: In most of the unity talks I noticed compare tag with the collider. And about the tag, I used it whenever I want to confirm the tag of the specific gameObject within the script.
Your answer
Follow this Question
Related Questions
Using the OnTriggerEnter ∁aring tags correctly. 1 Answer
Tag comparision with a string as variable doesnt work 4 Answers
Ignore Collision with Tag Error. 1 Answer
Tagged Load level 1 Answer
gameObject tag 2 Answers