Advanced GamePlay Tag Manager

Introduction

The Advanced Gameplay Tags Manager System (AGTMS) is a production-ready Unreal Engine plugin designed to simplify and enhance the control of Gameplay Tags within any game project.
It provides developers with a clean, structured approach to managing tags across multiple layers, ensuring consistent behavior, easier debugging, and complete control over active, blocked, and permanent states.
The system is fully blueprint-friendly and can be integrated seamlessly into both small prototypes and large-scale projects.

Why this component ?

• Multi-Layer Tag System

Active, Blocked, and Permanent layers for full control over character states.

• Smart Validation Checks

Automatic protection against invalid add/remove operations using layered rules.

• Bi-Directional Conflict Rules

Flexible conflict engine that prevents incompatible tags in both directions.

• Runtime Tag Replacement

Instantly swap tags (e.g., unarmed → rifle) with zero manual logic.

• Event-Driven Architecture

Dispatchers for tag added/removed, blocked tags, conflicts events.

• Runtime Blacklist Support

Temporarily restrict certain tags inside zones, triggers, or gameplay states.

• Save & Load Ready

Built-in serialization for restoring full tag state across levels or sessions.

• Blueprint-Only, High Performance

No ticks, clean logic, scalable, and fully compatible with Animation Blueprints & Choosers.

• Plug-and-Play Integration

Drop the component in any character and start using it immediately.

eliminates the complexity of managing large tag systems by offering a unified, reliable solution.
Instead of manually creating rules, checks, and tag validations, developers can rely on a powerful, pre-built framework that reduces development time, prevents logic errors, and keeps gameplay behavior consistent.
This plugin is designed to fit any workflow, whether you're building a first-person shooter, an open-world adventure.

why built gameplay tags framework Even though it's built in ?

Unreal Engine gives you : GameplayTag, GameplayTagContainer, Add Tag, Remove Tag, MatchesTag, HasTag...etc
There are no : [PermanentLayer][ActiveLayer][BlockedLayer]
Conflict Handling, events dispatchers , rule logic ..... and others things
This gives your game a AAA level of control—especially if you're going to do an Ability System or Character States.
Our component is professional State Management ,
You are the one who designs the rules of the system.
also unreal engine not gives you Multi-Tag Operations with Array of tags , this component plug & play , reusable
GamePlay Tags in Unreal Engine are just the foundation.


🎯 Summary


We built a complete framework on top of them:
✔ Active/Blocked/Permanent Layers
✔ Conflict System
✔ Debug System
✔ Events
✔ Tag Utilities
✔ Multi-Tag System
✔ Reusable Component
✔ AAA Architecture

This isn't readily available and gives your game significantly more power, control, and organization.
You simply need to employ it in your own way to build your game and benefit from it.

Installation & migrate

1 - when you download the project you will have this files :
2 - Migrate GP_TagManager to your project content folder
  • Content
    • GameplayTagManager
      • GP_TagManager (this folder we will migrate to our project)
        • Data
          • DataTable
            • DT_GameplayTagManager.uasset
          • Structure
            • Nested
            • Save_load_state
        • GameplayTagManager.uasset
      • Example (basic example for how to use)
      • Documentation (docs to guide you)


3 - Then go to your character or any actor blueprint you want to use component for him and add the component
4 - then you should initialize component by calling initalizepermtags function on event begin play
5 - Then, in the actortype input field, give a name to the character to whom you want to add the component. A specific name is not required.

6 - Last thing you should do go to DataTable folder then edit [DT_GameplayTagManager]
  • Content
    • GameplayTagManager
      • GP_TagManager (this folder we will migrate to our project)
        • Data
          • DataTable
            • DT_GameplayTagManager.uasset
6 - You will see table structure like that let us explain what is that exactly
RowName PermanentTags Conflict rules
RowName == ActorType PermanentLayer tag + array(conflicted with tags)
7 - we say Character have permanentTag = type.police and Jump conflict with Aiming

then we should type character in actortype input in initializepermtag function to select the right row from dataTable
also if you forget to reverse the rule like can't aiming while jumping don't worry conflict rule will check it in biDirectional

Compatible Versions :

Component created for : Windows / UE 5.3 - 5.7
but component should work in any platform or version that support gameplay tags
Sample project created in : Windows / UE 5.6 - Ue 5.7


Core Concepts


1. Active Tags Layer

Represents the tags currently applied to the character during gameplay.
These tags define the character’s live state (e.g.)

character.movement.run character.weapon.rifle
2. Blocked Tags Layer

A temporary blacklist that prevents certain active tags from being added.
Useful for restricted areas, gameplay zones, physics puzzles, stealth rooms, etc.


3. Permanent Tags Layer

A high-level category reserved for tags that must never be removed unless explicitly forced.
Useful for class attributes, character abilities, or permanent game modes.


4. Conflict Rules (Bi-Directional)

A powerful rule engine that prevents incompatible tags from co-existing.
The check works both ways In case you forgot to add the reverse rule:

If A conflicts with B → B conflicts with A If B is active → A cannot be added If A is active → B cannot be added

This guarantees stable & predictable gameplay logic.


5. Tag Replacement

A shortcut operation to swap tags immediately.
Example:

aiming.unarmedaiming.rifle
6. Serialization Support

You can save and restore the entire tag state using built-in functions:

GetSerializedTagsLoadSerializedTags

Useful for respawns, save systems, or switching levels.


7. Event Dispatchers

The system fires multiple events whenever tags change:

OnTagAddedOnTagBlocked OnTagRemovedOnTagConflict OnTagsSerializedOnTagsLoaded

Events allow disconnected systems (UI, animations, weapons, effects…) to react instantly.


📘 API Documentation 📘


This section provides a complete reference for all public functions included in the Advanced Gameplay Tags Manager Component. Each function is organized by category and explained in a clear, concise, and technical manner.

1. Initialization


Called once on BeginPlay. Loads default permanent tags from component settings and pushes them into:
Permanent Layer
Active Layer
Ensures consistent startup state.
Input: Target(Obj ref)Component Reference
Input: ActorType(Name)RowName RowName == ActorType in DataTable to fetch the row for specific ActorType
Input: Debug(Bool)True/False this debug bool print messages on screen to see if everything work correctly or not
Logic :
1. Prevent twice calling and print error if that happend
2. Validation for inputs to make sure inputs not empty or ActorType is wrong
3. Check for any duplicated values and print error message
4. Check for any Conflict rules if we add 2 conflicted tags with each other
5. Prepare active layer and permanent layer [Success]

2. Add Operations


AddActiveTag()


Adds a single Gameplay Tag to the Active Layer.
This operation performs full validation before adding the tag to ensure system stability and predictable behavior.
Input: Tag(GameplayTag) → Tag we want to add.
Input: Print(bool) → To print debug messages for development.
Output: IsAdded(bool) → To use it for conditions.
Output: Reason(String) → To print Reason to know success or why fail or just use Print(True)

Validation Steps:
When calling this function, the system automatically checks:

Check Duplicated
1. If the tag exists in Active or Blocked layer → operation fails.

Permanent Layer Rule Check
Permanent tags always override; conflicts are respected.

Bi-Directional Conflict Rules
The system checks both:
Active tags conflicting with the new tag
New tag conflicting with active tags
Ensures consistency even if the user forgets to define the reverse rule.

AddActiveTags(Array)


Adds multiple tags into the Active Layer in a single batch operation. Each tag is validated independently using the exact same logic as AddActiveTag().

Input: Tags(GameplayTagContainer) → Tags we want to add.

Behavior:
*Tags are added sequentially
*Failed tags do NOT stop the batch
Each tag runs:
*Block check
*Permanent check
*Conflict rules (bi-directional)
*Duplicate prevention



AddBlockedTag()


Adds a single Gameplay Tag to the Blocked Layer.
Blocked Tags immediately prevent any tag from being activated if it appears in this list.
This layer has the highest priority in the system.

Input: Tag(GameplayTag) → Tag we want to add.
Input: Print(bool) → To print debug messages for development.
Output: IsAdded(bool) → To use it for conditions.
Output: Reason(String) → To print Reason to know success or why fail or just use Print(True)

Validation Steps
When you call AddBlockedTag, the system performs:
Permanent Layer Check
Permanent tags cannot be blocked.
If the user tries → operation fails.
Duplicate Prevention
If the tag is already in Blocked or Active → operation fails silently.
(Ensure you removed it from active layer before add to blocked tags.)
Behavior
When a tag becomes blocked:
It cannot be added to Active.
Any function attempting to activate the tag will fail.
Used for restricted areas, forbidden actions, global silencing, etc.
Best Use Cases
Restricted zones (disable weapon usage, jumping, aiming…)
Cutscenes
UI menus → disable character control
Stun / freeze states
Any "hard lock" mechanic


AddBlockedTags(Array)


Same as AddBlockedTag

Adds multiple tags to the Blocked Layer in one batch.
Each tag passes through full validation independently.

3. Remove Operations


RemoveActiveTag()


Removes a single tag from the Active Layer.
Input: Tag(GameplayTag) → Tag we want to remove.
Input: Print(bool) → To print debug messages for development.
Output: IsRemoved(bool) → To use it for conditions.
Output: Reason(String) → To print Reason to know success or why fail or just use Print(True)

Behavior
If the tag is active → it is removed.
If the tag is not active → operation fails silently (returns false).
Cannot remove Permanent tags .

Best Use Cases
Stopping an action (stop aiming, stop sprinting…)
State transitions (run → idle)
Input releases

RemoveActiveTags(Array)


Batch-removes multiple active tags at once.
Input: Tag(GameplayTag) → Tag we want to remove.
Input: Print(bool) → To print debug messages for development.
Output: IsRemoved(bool) → To use it for conditions.
Output: Reason(String) → To print Reason to know success or why fail or just use Print(True)

Behavior
Each tag passes:
Active check
Silent failure if not active
Cannot remove Permanent tags .

Best Use Cases
Resetting movement states
Clearing temporary states after stun / hit
Ending multiple actions simultaneously


RemoveBlockedTag()


Removes a single tag from the Blocked Layer.
Input: Tag(GameplayTag) → Tag we want to remove.
Input: Print(bool) → To print debug messages for development.
Output: IsRemoved(bool) → To use it for conditions.
Output: Reason(String) → To print Reason to know success or why fail or just use Print(True)

Behavior
If the tag is blocked → it is removed.
If the tag is not blocked → operation fails silently (returns false).

Best Use Cases
Leaving a restricted zone
Re-enabling weapon usage
Releasing character from “hard lock” states (cutscene end, stun end)

RemoveBlockedTags(Array)


Batch-removes multiple blocked tags at once.
Input: Tag(GameplayTagContainer) → Tag we want to remove.
Input: Print(bool) → To print debug messages for development.
Output: IsRemoved(bool) → To use it for conditions.
Output: Reason(String) → To print Reason to know success or why fail or just use Print(True)

Behavior
Each tag passes:
Active check
Silent failure if not blocked
If one tag fail all fail

Best Use Cases
Resetting movement states
Clearing temporary states after stun / hit
Ending multiple actions simultaneously

4. Replace Operations


ReplaceActiveTag()


Replaces an existing active tag with another tag.
Input: OldTag(GameplayTag) → old Tag we want to replace.
Input: NewTag(GameplayTag) → New tag we want to add
Input: Debug(bool) → To print debug messages for development.
Output: IsReplaced(bool) → To use it for conditions.

Behavior
Checks if OldTag is active.
Removes OldTag.
Runs full validation on NewTag:
Conflict rules (including bidirectional checks)
Duplicate prevention
If all checks pass → adds NewTag.
If the new tag fails validation → the replace is canceled and the old tag is still in layer.

Best Use Cases
Switching movement states (Idle → Run, Unarmed → Armed…)
Changing character stances (HipFire → ADS)
Smooth transitions without needing manual Remove + Add
Weapon switching
Replacing aim states
Ensuring error-free swapping when only one state should exist at a time

Replaces a blocked tag with another blocked tag.

ReplaceBlockedTag()


Replaces an existing Blocked tag with another tag.
Input: OldTag(GameplayTag) → old Tag we want to replace.
Input: NewTag(GameplayTag) → New tag we want to add
Input: Debug(bool) → To print debug messages for development.
Output: IsReplaced(bool) → To use it for conditions.

Behavior
Checks if OldTag is blocked.
Removes OldTag.
Runs full validation on NewTag:
Conflict rules (including bidirectional checks)
Duplicate prevention
If all checks pass → adds NewTag.
If the new tag fails validation → the replace is canceled and the old tag still in the layer.

Best Use Cases
Changing restricted zones behavior
Upgrading restrictions (Block_Aim → Block_All_Weapons)
Dynamic rule updates during gameplay (cutscenes / alarms / stealth transitions)

5. Clears Operations


clearActiveTags()


Clears all Active Tags stored inside the gameplay container.
Input: print(bool) → To print debug messages to see if layer empty or not for development.

Behavior
If KeepPermanent = true → Permanent tags remain untouched.
If KeepPermanent = false → All active tags are removed, including permanent ones.
Use Cases:
Resetting the active state before applying new tag logic.
Cleaning up temporary tags after an ability or animation ends.
Performing a soft or full reset depending on the KeepPermanent setting.

clearBlockedTags()


Clears all Blocked Tags stored inside the gameplay container.
Input: print(bool) → To print debug messages to see if layer empty or not for development.

Use Cases:
Preparing a clean state when switching gameplay modes or states.

clearPermanentTags()


Clears all Permanent Tags stored inside the gameplay container.
Input: print(bool) → To print debug messages to see if layer empty or not for development.

Use Cases:
When the gameplay system needs to wipe all persistent states.

6. Get Operations


GetActiveTags(output)


Returns the current Active Gameplay Tag Container stored in the component.
Input: print(bool) → To print tags in the container for development.
ReturnValue: Output(GameplayTagContainer) → full snapshot of all active tags, including both temporary and permanent ones because permanent mean always active during.

Use Cases:
Debugging current tag logic.
Feeding other systems (abilities, movement, UI) with the current active tag set.

GetBlockedTags(output)


Same as GetActive but it's get BlockedTags

GetPermanentTags(output)


Same as GetActive,Getblocked but it's get PermanentTags

7. CheckLayers Operations


IsTagActive(Result)


Checks whether a specific Gameplay Tag is currently active inside the component.

Returns:
Boolean – True if the tag exists in the Active container (temporary or permanent), otherwise False.
Use Cases:
Ability system logic (is player aiming? sprinting? stunned?).
Conditional gameplay branching.

IsTagBlocked(Result)


Checks if the specified Gameplay Tag is currently blocked and should not be activated.

Returns:
Boolean – True if the tag exists in the Blocked container , otherwise False.
Use Cases:
Preventing tag activation (e.g., can’t sprint while crouching(Anyway blocked tags will not active by default)).
Controlling complex bidirectional restrictions.

IsTagPermanent(Result)


Checks whether a specific Gameplay Tag is currently exist inside the Permanent Layer.

Returns:
Boolean – True if the tag exists in the Permanent container , otherwise False.
Use Cases:
Loading player class, equipment, or game mode–level states.
Ensuring long-term tags remain unchanged unless manually removed.
Debugging initialization states.

8. Save / Load State


GetSerializedState


Generates a serialized snapshot of the ActiveTags layer current state.
This snapshot is used for saving or restoring gameplay actiev tags at runtime.

Input:
RuntimeBlacklist (GameplayTagContainer)
A list of tags that should be excluded from the save (e.g., temporary combat states, session-only flags).

Output:
SavedState (GameplayTagContainer) A container including all valid tags that can be restored later, after removing any blacklisted entries.

Logic Summary:
Copy Active Tags.
Remove tags that appear in the RuntimeBlacklist.
Return the final cleaned container as the saved state.

Use Cases:
Saving player state when entering/exiting restricted zones.
Checkpoint systems.
Networking or RPC sync.(Not tested in multiplayer online games , but it will be in next updates to make component compatible with online games)


LoadSerializedState


Loads a previously saved tag structure and restores it into the component while preserving the Permanent Tags layer.

Input:
SerializedStructure (struct – output of GetSerializedState)
Contains the tags that must be re-applied.

Logic Summary:

1. Restore Permanent Tags first:
Set ActiveTags = PermanentTags (permanent tags always take priority).

2. Merge Saved Tags:
For each tag in the serialized structure:
If the tag is not already permanent, add it back to ActiveTags.
Permanent tags are skipped because they were already restored in step 1.
also blocked tags will be restored to blocked layer.
split the structure to see the arrays of active and blocked tags individually.


3. Ensure no duplicates and no conflicts (handled internally).


Use Cases:
Re-entering a restricted area with correct previous state.
Player respawn or level reload.
Applying external saved states without breaking the permanent layer.

9. Reseter


ResetComponent()


Resets the component to a clean state by removing all Active and Blocked tags while preserving Permanent Tags.
Permanent Tags always remain active throughout the entire game lifetime and are re-applied automatically after the reset.

Use Cases:
Resetting player states when entering or leaving special gameplay zones.
Cleaning temporary combat/interactions state.
Soft-reload of character state without losing long-lived attributes.

10. Internal Utility(Private)


CheckConflictRules()


Validates whether an input tag can be added by checking the Conflict Rules defined inside the DataTable.
This includes a full bi-directional conflict check, ensuring the user can't forget to define the reverse conflict.

Logic Summary
Validate the input tag (must not be empty).
Validate the ActorType (must not be “None”).
Fetch the corresponding row from the Conflict Rules DataTable by compare ActorType with RowName.
If the row does not exist → operation stop and print critical message error

If the row exists:
Check self-conflict rule for the input tag to prevent tag conflict with it-self.
Check any conflict rules defined for other tags that conflict with the input tag.
Perform reverse (bi-directional) conflict check:

Example:
If A conflicts B
But the developer forgot to add "B conflicts A"
The system still catches it.


If any conflict rule is triggered → stop the whole operation and return false.
If nothing is violated → return true.
Notes:
Internal private function—not callable externally.
Guarantees stable, predictable, consistent gameplay tag behavior.


CheckDuplicated()


Internal helper function used to prevent adding a tag that already exists in either the Active or Blocked layers.

Logic Summary
Input Tag is checked against the Active container.
Then checked against the Blocked container.
If found in any of them → the tag is considered duplicated, and the caller function must abort the operation or remove it first.

Notes
This is a private function, not accessible outside the Actor Component.
Exists only for internal data integrity.

Event Dispatchers



How to use with AnimationBlueprintGraph(ABP_) ?


Overview

To safely access your Gameplay Tags Component from the Animation Blueprint—without access errors, thread issues, or invalid references—you must use a shadowing structure variable.
This ensures the AnimBP works only with copied data, not live references, which prevents runtime crashes and keeps performance high.
1. Shadowing Variable (Struct-Based Animation State Cache)
The Animation Blueprint runs on a separate thread and cannot reliably read Actor Component data directly.
So we create a structure variable inside the AnimBP, for example such as:
Struct: AnimStateData
Contains:
Active Tags (GameplayTagContainer)
Blocked Tags (GameplayTagContainer)
Permanent Tags (GameplayTagContainer)
Optional booleans (IsAiming, IsArmed, etc) — derived from tags
Or any other data that is relevant to your project
This struct becomes the safe mirrored state of the component.
2. RefreshState Function (Called From Character → AnimBP)
The Character BP pushes updated tag data to the AnimBP every time something changes.
Create a Custom Event:
Event UpdateTagState (Input: AnimStateData Struct) → Set the shadowing variable
Whenever tags change: OnActiveTagAdded OnActiveTagRemoved OnBlockedTagAdded OnBlockedTagRemoved Replace events Clear events
You simply call UpdateTagState and pass the struct.
This guarantees the AnimBP is always synced.

Other Example in sample project with MotionMatching + ChooserTable


Why This Integration Works Perfectly


✔ Zero access errors ✔ Zero crashes ✔ Safe for multithreading ✔ UI / Animation / Gameplay always synced

✔ Perfect for Motion Matching + Chooser ✔ Component remains modular and reusable ✔ Production-ready for AAA pipelines >


1. Create Structure and call it → AnimDataState
2. add booleans variable you need and variables for gameplaytags containers (Anyway it just for example you can make it as you like )
3. go to your Character blueprint then create new function let's call it UpdateAnimStateTags
4. create a variable call it → AnimStateData and set variable type → your structure
5. Then Create some local variables to fill our structure like shown in the image

6. by using function IsTagActive we can fill our booleans
also tags container we can use GetFunctions to save Tags container
7. let's pass data to AnimStateData(struct).
8. go to your animation blueprint and create a variable AnimStateData

9. let's fill it in Game thread don't do anything in animation blueprint again close it
go back to function UpdateAnimStateTags in your character blueprint
send Data from the character variable cast it to animation graph variable

Now Data passed to animation blueprint in game thread
[Let's see how to use it with chooser Table]


you can sync tags by add node timer by event and check looping in 0.02 50Hz or 0.033 30Hz





you can also use event dispatchers ...




Continued Updates & Support

Discord Link for any report or feedback

We aim to keep the Advanced Gameplay Tags Manager System clean, stable, and easy to integrate.
Future updates will focus on:
Additional quality-of-life functions based on community feedback
More plug-and-play examples (Animation BP, Motion Matching, Restricted Zones, Item Systems)
Improved error-handling and debugging helpers
Optional performance-friendly utilities for large projects
Documentation refinements and new usage guides
We are committed to supporting the system with practical, meaningful updates—not unnecessary features.