Gameplay Ability System Course Project - Development Blog

Hello again everyone! Welcome to another entry in this on-going blog/development thread for my GAS Course Project. For more context of this project, please see the very first post in this thread, and as usual, you can find my socials here:

Twitch : Twitch
Discord : UE5 - GAS Course Project - JevinsCherries
Tiktok : Devin Sherry (@jevinscherriesgamedev) | TikTok
Youtube : Youtube
Twitter : https://twitter.com/jevincherries
Instagram : Jevins Cherries Gamedev (@jevinscherriesgamedev) • Instagram photos and videos


Today we are going to talk about Ability Tag Category Remapping, and how you can use these categories to help with project-wide organization of your Gameplay Tags within the context of the Gameplay Ability System. A big shout-out to my colleague at CD Projekt Red, Eryk Dwornicki for showing me this. From what I have researched online, there isn’t any sort of explicit documentation talking about Ability Tag Category Remapping, so this blog post may serve as the first to do so. If others find documentation on this subject, please let me know so that this post can be updated accordingly. Make sure to follow Eryk on Twitter (X): x.com.


Classes to research on your own:

https://docs.unrealengine.com/4.26/en-US/API/Runtime/GameplayTags/FGameplayTagContainer/
https://docs.unrealengine.com/4.27/en-US/API/Plugins/GameplayAbilities/Abilities/UGameplayAbility/

Additional Reading:


What is Ability Tag Category Remapping?

One of the more powerful aspects of Gameplay Tags are that they are use a hierarchal structure of parent/child to organize tags into categories. In the Gameplay Ability System plugin, it uses Gameplay Tags for different aspects of the plugin; for ability tag containers, gameplay effect containers, gameplay events, and more. With Ability Tag Category Remappings you can add a requirement of tag categories to fit one or more branches of your tag hierarchy in order to be visible when adding them to the aforementioned aspect of GAS. To better explain, let’s first use the Ability Tag Container found inside of the UGameplayAbility class:

GameplayAbility.h

	// ----------------------------------------------------------------------------------------------------------------
	//	Ability exclusion / canceling
	// ----------------------------------------------------------------------------------------------------------------

	/** Abilities with these tags are cancelled when this ability is executed */
	UPROPERTY(EditDefaultsOnly, Category = Tags, meta=(Categories="AbilityTagCategory"))
	FGameplayTagContainer CancelAbilitiesWithTag;

	/** Abilities with these tags are blocked while this ability is active */
	UPROPERTY(EditDefaultsOnly, Category = Tags, meta=(Categories="AbilityTagCategory"))
	FGameplayTagContainer BlockAbilitiesWithTag;

	/** Tags to apply to activating owner while this ability is active. These are replicated if ReplicateActivationOwnedTags is enabled in AbilitySystemGlobals. */
	UPROPERTY(EditDefaultsOnly, Category = Tags, meta=(Categories="OwnedTagsCategory"))
	FGameplayTagContainer ActivationOwnedTags;

	/** This ability can only be activated if the activating actor/component has all of these tags */
	UPROPERTY(EditDefaultsOnly, Category = Tags, meta=(Categories="OwnedTagsCategory"))
	FGameplayTagContainer ActivationRequiredTags;

	/** This ability is blocked if the activating actor/component has any of these tags */
	UPROPERTY(EditDefaultsOnly, Category = Tags, meta=(Categories="OwnedTagsCategory"))
	FGameplayTagContainer ActivationBlockedTags;

	/** This ability can only be activated if the source actor/component has all of these tags */
	UPROPERTY(EditDefaultsOnly, Category = Tags, meta=(Categories="SourceTagsCategory"))
	FGameplayTagContainer SourceRequiredTags;

	/** This ability is blocked if the source actor/component has any of these tags */
	UPROPERTY(EditDefaultsOnly, Category = Tags, meta=(Categories="SourceTagsCategory"))
	FGameplayTagContainer SourceBlockedTags;

	/** This ability can only be activated if the target actor/component has all of these tags */
	UPROPERTY(EditDefaultsOnly, Category = Tags, meta=(Categories="TargetTagsCategory"))
	FGameplayTagContainer TargetRequiredTags;

	/** This ability is blocked if the target actor/component has any of these tags */
	UPROPERTY(EditDefaultsOnly, Category = Tags, meta=(Categories="TargetTagsCategory"))
	FGameplayTagContainer TargetBlockedTags;

As you can see in the UPROPERTY of each tag container, there is the meta specifiier, (Categories=“”) where, by default, there are categories that label each container. AbilityTagCategory, OwnedTagsCategory, SourceTagsCategory, and TargetTagsCategory. What you can do now is in Project Settings → Gameplay Tags, in the Category Remapping section, you can add entries for each Base Category and remap them to one or more branches of your Gameplay Tag hierarchy. You can also pick and choose which categories you’d like to remap, and even create your own categories!

An example in my personal project where I created my own custom categories are found in the TargetTagsGameplayEffectComponent and AssetTagsGameplayEffectComponent classes, where instead of them sharing the OwnedTagsCategory by default, I created new categories called GameplayEffectOwnedTagsCategory and GameplayEffectAssetTagsCategory respectively. The reason for this is because I wanted to differentiate between the tags used for Gameplay Effects and the tags used for Gameplay Abilities.

Here is the AbilityTagsCategory before & after:

Here is the OwnedTagsCategory before & after:


TargetTagsGameplayEffectComponent.h

private:
/** These tags are applied (granted) to the target actor of the Gameplay Effect. The Target would then “own” these Tags. */
UPROPERTY(EditDefaultsOnly, Category = None, meta = (DisplayName = “Add Tags”, Categories = “GameplayEffectOwnedTagsCategory”))
FInheritedTagContainer InheritableGrantedTagsContainer;


AssetTagsGameplayEffectComponent.h

private:
/** The GameplayEffect’s Tags: tags the the GE has and DOES NOT give to the actor. */
UPROPERTY(EditDefaultsOnly, Category = Tags, meta = (DisplayName = “AssetTags”, Categories = “GameplayEffectAssetTagsCategory”))
FInheritedTagContainer InheritableAssetTags;

Why Use Ability Tag Category Remapping?

Anyone who has worked with Gameplay Tags on a project will tell you how easy it is for tags to explode in regards to the shear number of tags and their uses throughout the project. On multiple projects, I have seen tags with mispelling, duplicate tags in different branches of the hierarchy that serve the same purposes, and developers adding tags without any sort of documentation for that tag or even using that tag for its intended use. What I believe Ability Tag Category Remapping serves as a way to control and direct developers to the appropriate branches of the Gameplay Tag hierarchy to add their tags in order to use them for their intended purposes. Need to add an Ability Tag for your gameplay ability? Add a tag to the Ability.Type hierarchy! Need an Asset Tag for your burn status Gameplay Effect? Use the Effect.AssetTag hierarchy! By doing so, you remove the potential of using different tag hierarchies for different purposes and reduce the human error when it comes to using Gameplay Tags.


Thank you for taking the time to read this post, and I hope you were able to take something away from it. Please let me know if I got any information wrong, or explained something incorrectly! Also add any thoughts or questions or code review feedback so we can all learn together :slight_smile:


Next Blog Post Topic:

*Gameplay Effect UI Data for Status Effects

4 Likes