GAS Helpers v0.2.0
Small C++ helpers for the Unreal Engine 5 Gameplay Ability System in multiplayer games: safe ASC lookup, activate-by-tag with a result, replicated loose tags, SetByCaller spec builder, cooldown time by tag, ability input by tag with Enhanced Input, ASC state dump, and async attribute and tag-count watchers for UI without Tick.
- The problem
- Six common GAS questions with no clear answer from the engine: why the ASC is null, why an ability did nothing, why a tag never reached clients, why an effect applied at 0.
- What it replaces
- Breakpoints, print strings and comparing server and client state by hand.
- What it saves
- Our estimate: an hour or two each time one of these bugs comes up, which on a GAS project is often. One call per helper.
- Who it is for
- C++ programmers already using GAS in a multiplayer game.
Small C++ helpers for the Unreal Engine 5 Gameplay Ability System in multiplayer games. Free, MIT licensed, no sign-up.
Unreal Engine 5.5 to 5.8. Compiled clean (0 errors, 0 warnings) on 5.5, 5.6, 5.7 and 5.8, and covered by automation tests that run each helper against a real Ability System Component on every one of those versions (standalone world, so the tests exercise server-side behaviour; replication itself is not simulated). Still a preview: test it in your project, and send problems to contact@reignancestudios.com.
What is inside
| Helper | What it fixes | Tutorial |
|---|---|---|
FindAbilitySystemComponent | Null ASC when it lives on the PlayerState | ASC on PlayerState |
TryActivateAbilityByTag | "Nothing happens" with no reason: tells you NotGranted vs Blocked | Ability fires twice or not at all |
AddReplicatedLooseTag / RemoveReplicatedLooseTag | Loose tags that exist on the server but never reach clients | Replicated loose tags |
MakeSpecWithSetByCaller | Effects applied with magnitude 0 because a SetByCaller was missed | Predicted cost and cooldown |
DumpAbilitySystemState | Comparing server and client ASC state by hand | Ability fires twice or not at all |
URSAsyncWatchAttribute | Health bars polling in Tick | Attribute UI without Tick |
URSAsyncWaitTagCount (new in 0.2.0) | Stack, charge and status UI polling tag counts in Tick | Replicated loose tags |
GetCooldownRemainingByTag (new in 0.2.0) | Cooldown widgets that search active effects by hand, or miss the predicted cooldown | Predicted cost and cooldown |
PressAbilityInputByTag / ReleaseAbilityInputByTag + URSAbilityInputConfig (new in 0.2.0) | Abilities bound to numeric input IDs; WaitInputRelease that never fires | Ability fires twice or not at all |
Not included on purpose: a local-only gameplay cue helper. The engine already has one, UGameplayCueFunctionLibrary::ExecuteGameplayCueOnActor (and Add/Remove), which runs the cue on this machine only.
The Examples folder holds a PlayerState, Character, AttributeSet and a predicted Dash ability. They are not compiled with the plugin: copy them into your game module.
Install
- Download the ZIP and unzip it into
YourProject/Plugins/RSGasHelpers. - Make sure the Gameplay Abilities and Enhanced Input plugins are enabled (both are on by default in new projects).
- Add
"RSGasHelpers"toPublicDependencyModuleNamesin your game's.Build.csif you call it from C++. - Regenerate project files and build.
Usage
#include "RSAbilitySystemLibrary.h"
const ERSActivateResult Result =
URSAbilitySystemLibrary::TryActivateAbilityByTag(this, TAG_Ability_Dash);
if (Result == ERSActivateResult::Blocked)
{
UE_LOG(LogTemp, Warning, TEXT("%s"),
*URSAbilitySystemLibrary::DumpAbilitySystemState(this));
}Bind abilities to input by tag
Make a URSAbilityInputConfig data asset, add one row per Input Action with the ability tag it starts, then bind it in your character:
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
InputConfig->BindAbilityActions(CastChecked<UEnhancedInputComponent>(PlayerInputComponent),
this, &AMyCharacter::AbilityInputPressed, &AMyCharacter::AbilityInputReleased);
}
void AMyCharacter::AbilityInputPressed(FGameplayTag Tag) { URSAbilitySystemLibrary::PressAbilityInputByTag(this, Tag); }
void AMyCharacter::AbilityInputReleased(FGameplayTag Tag) { URSAbilitySystemLibrary::ReleaseAbilityInputByTag(this, Tag); }A press starts every granted ability whose tags include the row's tag. If the ability is already active, the press goes to it instead, with its activation prediction key, so WaitInputPress and WaitInputRelease work for charge-and-release abilities. In Blueprint, call the two functions from the Started and Completed pins of an Enhanced Input event.
Help
These helpers fix single symptoms. If your abilities still desync in packaged builds or at real latency, the cause is usually ownership or prediction setup across the project. A Diagnostic finds it in two days.
Changelog
v0.2.0 (2026-10-31)
- New
URSAsyncWaitTagCount(Wait Gameplay Tag Count): fires on every count change of a tag, with the current count first. - New
GetCooldownRemainingByTag: time left and duration of the cooldown that grants a tag, including the predicted cooldown on the owning client. - New
PressAbilityInputByTag,ReleaseAbilityInputByTagand theURSAbilityInputConfigdata asset: Enhanced Input actions bound to abilities by tag, with presses forwarded to active abilities forWaitInputPress/WaitInputRelease. - Needs the Enhanced Input plugin.
- Automation tests for every helper, run on UE 5.5 to 5.8.
v0.1.0 (2026-10-30)
- First preview release.
URSAbilitySystemLibrary: FindAbilitySystemComponent, TryActivateAbilityByTag, AddReplicatedLooseTag, RemoveReplicatedLooseTag, MakeSpecWithSetByCaller, DumpAbilitySystemState.URSAsyncWatchAttribute: attribute watcher for UI without Tick.- Examples: PlayerState with ASC, Character init, AttributeSet with prediction-safe OnReps, predicted Dash ability.
- On UE 5.7 and later,
RemoveReplicatedLooseTagremoves through the container overload: the engine's single-tag path does not fireAnyCountChangewhen a count drops without reaching 0.