<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Marko Petrić</title>
    <description>The latest articles on DEV Community by Marko Petrić (@marko-ue).</description>
    <link>https://dev.to/marko-ue</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3921699%2F37f639a9-f894-4b3d-8f8a-2559e1ee8d79.png</url>
      <title>DEV Community: Marko Petrić</title>
      <link>https://dev.to/marko-ue</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/marko-ue"/>
    <language>en</language>
    <item>
      <title>Native Gameplay Tags in GAS</title>
      <dc:creator>Marko Petrić</dc:creator>
      <pubDate>Sat, 09 May 2026 12:09:26 +0000</pubDate>
      <link>https://dev.to/marko-ue/native-gameplay-tags-in-gas-53lb</link>
      <guid>https://dev.to/marko-ue/native-gameplay-tags-in-gas-53lb</guid>
      <description>&lt;h3&gt;
  
  
  What are gameplay tags and why should you use them
&lt;/h3&gt;

&lt;p&gt;Gameplay tags are essentially &lt;code&gt;FName&lt;/code&gt; wrappers, meaning they have a small upfront cost when first created but are very cheap to access and compare after that.&lt;/p&gt;

&lt;p&gt;Gameplay tags are used as a clean way to handle things like character and actor state, input and ability activation, damage types and resistances, and communication between systems. GAS also has built-in tag requirements for gameplay abilities. Essentially, wherever you'd traditionally use booleans or enums, gameplay tags are generally the better choice when working with GAS.&lt;/p&gt;




&lt;h3&gt;
  
  
  What are native gameplay tags and why should you use them
&lt;/h3&gt;

&lt;p&gt;Native gameplay tags are tags created in C++, rather than in the editor.&lt;/p&gt;

&lt;p&gt;The main reasons for creating native gameplay tags rather than using editor ones is for type safety (autocomplete, no typo risk), which makes native ones safer, faster and easier to access through code.&lt;/p&gt;

&lt;p&gt;Note: Any gameplay tag changes made in blueprint reflect to C++ code and vice versa. The Ability System Component does not care about the source of changes.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Storing tags&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Before creating native tags, you need a place to store them. A simple way would be to manually create empty &lt;code&gt;.h&lt;/code&gt; and &lt;code&gt;.cpp&lt;/code&gt; files. For context, my project is called Comply, and I will be using that prefix for my tags, so my files will be named ComplyTags.&lt;/p&gt;

&lt;p&gt;After creating these files, you need to use &lt;code&gt;#pragma once&lt;/code&gt; at the top of the &lt;code&gt;.h&lt;/code&gt; file, and to include &lt;code&gt;CoreMinimal.h&lt;/code&gt; and &lt;code&gt;NativeGameplayTags.h&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#pragma once
&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"CoreMinimal.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"NativeGameplayTags.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One way of storing tags, which lets you access specific tags cleanly, is to use namespaces. After creating a base namespace, each other namespace should be named based on the kind of tags it will store - so, for example, you could have a namespace called States for all state related gameplay tags, or Abilities for all ability asset tags. It's also possible to have namespace hierarchies.&lt;/p&gt;

&lt;p&gt;This is just one way of storing them, but you can try any approach and see what you'd prefer. In this practical example, namespaces will be used.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Declaring tags&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To declare tags, you use the &lt;code&gt;UE_DECLARE_GAMEPLAY_TAG_EXTERN&lt;/code&gt; macro, and pass in the name of the tag you wish to use, as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="n"&gt;ComplyTags&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="n"&gt;ComplyAbilities&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;UE_DECLARE_GAMEPLAY_TAG_EXTERN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Primary_Ranger&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;UE_DECLARE_GAMEPLAY_TAG_EXTERN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Utility_Ranger&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;strong&gt;Defining tags&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;After declaration, tags need to be defined, and this is handled in the &lt;code&gt;.cpp&lt;/code&gt; file for your tags. First, you need to include the &lt;code&gt;.h&lt;/code&gt; file for the tags here, which in my case is &lt;code&gt;ComplyTags.h&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"AbilitySystem/ComplyTags.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;.cpp&lt;/code&gt; file, you need to make sure your namespace names and hierarchies match with the structure created in the &lt;code&gt;.h&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;To define the tags, you use the &lt;code&gt;UE_DEFINE_GAMEPLAY_TAG&lt;/code&gt;, and optionally &lt;code&gt;UE_DEFINE_GAMEPLAY_TAG_COMMENT&lt;/code&gt; which unlocks a third parameter that lets you add a comment for your tag that can be seen in the editor. For this macro, the first parameter is the tag name (the same one you passed in when declaring the tag), then the tag hierarchy (which is how the tag can be accessed in the editor), and then, optionally, the comment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="n"&gt;ComplyTags&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="n"&gt;ComplyAbilities&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;UE_DEFINE_GAMEPLAY_TAG_COMMENT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Primary_Ranger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ComplyTags.Abilities.Ranger.Primary"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Primary ability asset tag for ranger"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;UE_DEFINE_GAMEPLAY_TAG_COMMENT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Utility_Ranger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ComplyTags.Abilities.Ranger.Utility"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Utility ability asset tag for ranger"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Accessing and using native tags
&lt;/h2&gt;

&lt;h3&gt;
  
  
  In the editor
&lt;/h3&gt;

&lt;p&gt;Any tags created natively appear in the gameplay tag list found in Project Settings, even among any tags you may choose to create in the editor.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fle1h6pl21jg7b5qgnf3p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fle1h6pl21jg7b5qgnf3p.png" alt="An image showing gameplay tags in the editor" width="267" height="287"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;They can be assigned in the editor for all purposes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe6hk9b35jyjj32h526tz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe6hk9b35jyjj32h526tz.png" alt="An image showing the usage of gameplay tags in the editor" width="613" height="35"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  In C++
&lt;/h3&gt;

&lt;p&gt;Using native gameplay tags in C++ is where they really prove their worth over ones created in blueprint. When accessing gameplay tags created in the blueprint through C++, you would often have to use &lt;code&gt;FGameplayTag::RequestGameplayTag(FName("Tag.Hierarchy"));&lt;/code&gt; which is prone to typos and has a slight overhead.&lt;/p&gt;

&lt;p&gt;For accessing native ones in code, you just have to include the &lt;code&gt;.h&lt;/code&gt; of where you store your native gameplay tags, which in my case is &lt;code&gt;ComplyTags.h&lt;/code&gt;, wherever you need to access them. Then, you type in the name of the base namespace, and use double colons to navigate to different namespaces and to a specific tag.&lt;/p&gt;

&lt;p&gt;Examples of using native gameplay tags in code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Checking if an actor has a certain tag&lt;/span&gt;
&lt;span class="n"&gt;FGameplayTagContainer&lt;/span&gt; &lt;span class="n"&gt;Tags&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;Character&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;GetAbilitySystemComponent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;GetOwnedGameplayTags&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Tags&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Tags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HasTagExact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ComplyTags&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;States&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;State_Aiming&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;PlayMontageAndBindDelegates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AbilityActivationMontageIronsights&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Using a native gameplay tag to pass in a set by caller data tag&lt;/span&gt;
&lt;span class="n"&gt;FGameplayEffectContextHandle&lt;/span&gt; &lt;span class="n"&gt;ReserveAmmoContextHandle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GetAbilitySystemComponentFromActorInfo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;MakeEffectContext&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;FGameplayEffectSpecHandle&lt;/span&gt; &lt;span class="n"&gt;ReserveAmmoSpecHandle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GetAbilitySystemComponentFromActorInfo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;MakeOutgoingSpec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="n"&gt;ActiveWeapon&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ReduceReserveAmmoEffectClass&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ReserveAmmoContextHandle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;UAbilitySystemBlueprintLibrary&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;AssignTagSetByCallerMagnitude&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="n"&gt;ReserveAmmoSpecHandle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ComplyTags&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SetByCaller&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SBC_ReduceRifleReserveAmmo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;AmmoSpent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;GetAbilitySystemComponentFromActorInfo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ApplyGameplayEffectSpecToSelf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ReserveAmmoSpecHandle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Registering a gameplay tag event by passing in a native tag&lt;/span&gt;
&lt;span class="n"&gt;GetAbilitySystemComponent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;RegisterGameplayTagEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="n"&gt;ComplyTags&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;States&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;State_Aiming&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;EGameplayTagEventType&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;NewOrRemoved&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;AddUObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;AComplyPlayerCharacter&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;OnAimingTagChanged&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  When you would prefer editor-created tags
&lt;/h3&gt;

&lt;p&gt;Native gameplay tags make sense when you are accessing them frequently in code, but editor tags are fine for quick one-off logic, for designers, or for quick prototyping.&lt;/p&gt;




&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Although not required, native gameplay tags are a great alternative to editor-created tags for a multitude of reasons, and I would recommend everyone to try using them.&lt;/p&gt;

&lt;p&gt;If you have any questions or feedback, feel free to contact me on LinkedIn, or email me: &lt;a href="mailto:petric.marko04@gmail.com"&gt;petric.marko04@gmail.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>unrealengine</category>
      <category>ue5</category>
      <category>gameplayabilitysystem</category>
      <category>cpp</category>
    </item>
  </channel>
</rss>
