I was also messing around with GameplayTags today. What Bruno mentioned works, something else to keep in mind since you mentioned the private constructors is that to make a tag from text like that, you have to include GameplayTagsModule.h, and then use UGameplayTagsManager::Get().RequestGameplayTag(“Special.Hover”). Not sure if that’s the recommended way or not but it worked for me.
Both produce errors:
Cannot convert from ‘const wchar_t [10]’ to ‘const FGameplayTag’
No overload matches the argument list, etc.
This seemed like a nice simple solution as I’ll be done a lot of Gameplaytag checks in the Tick, but I don’t see how text could be converted to GameplayTag, unless I’m missing something?
I could’ve sworn that it worked :eek: Meanwhile just use what I mentioned earlier. Make a new ***FGameplayTag TestTag = ******UGameplayTagsManager::Get().RequestGameplayTag(“Special.Hover”); ***and then use that tag for comparison. There are a lot of other useful functions in ***UGameplayTagsManager ***so read through those too.
Yeah I’m going to use that for now. It’ll be great in BeginPlay and such, problem is I’m using it 15+ times per tick on 100+ actors.
(I’m not too sure of the performance of requesting existing tags 1000 times per tick).
If *MatchesTag(TEXT(“myTagName”)) *does in fact work, that could be much easier on performance when ran so many times per tick.
MatchesTag(TEXT(“Blah”)) is far more inefficient than requesting a tag and storing it. Tags are basically just FNames (so they boil down to an integer compare once created). If you just passed in a string you’d be paying the cost of creating the FName every call.
I’d just put an array of the tag names you want somewhere, run through and request the tags at start up, then just use those whenever you are doing a tag check.
Correct, but again the previous call was technically expensive since it had to construct an FName at runtime - so I can see why they wanted to move away from that and force people to cache gameplay tags.
Alrighty, I think I’ve created a decent solution to my initial post. The below code is a 1 time conversion from GameplayTagContainer into a Name Array that can easily and quickly be searched at any time.
It seems pretty good to me, but let me know if there’s actually any big flaws/performance problems with this method.
Here’s what I’m using for an Item Chest where developers can select multiple item tags to spawn in the chest.
UPROPERTY(EditAnywhere, meta = (Categories = "Items")) FGameplayTagContainer ItemTag;
TArray<FName> NTags;
BeginPlay(){
//Convert GameplayTagContainer into array of names
for (int8 i = 0; i < ItemTag.Num(); i++) {
FString tagStr = ItemTag.GetByIndex(i).GetTagName().ToString();
int8 endDot = tagStr.Find(".", ESearchCase::IgnoreCase, ESearchDir::FromEnd);
if(endDot > -1) tagStr = tagStr.RightChop(endDot+1);
NTags.Add(*tagStr);
}
}
That also puts only the last tag into the list, removing the categories. So:
Items.Potions.MediumPotion
Items.Potions.HighPotion
Items.Bombs.FireBomb
Becomes MediumPotion, HighPotion, FireBomb. Easy to loop through and spawn the items. Also easy to do the quick lookups I was asking about before using:
Tags.Contains("MediumPotion");
For single GameplayTags, you can also easily use the below method to check if it contains a specific tag:
This method might be easier to search for single tags than requesting a fully typed out + categorized gameplay tag.
Whether it performs better or worse I don’t know, but might save typing-time in the long run for single lookups.
This is old, but to anyone finding this, ParseIntoArray is easier. It is definitely not faster. The comments on (almost) all of the C++ functions indicate that it is (relatively) slow and costly.
As a general rule, just because you can write 10 lines of code or call a function (1 line) does not mean the function is faster. Always look under the hood.