Quick answer: HasTag matches the tag and its children; HasTagExact matches only the exact tag. A query checking for “State.Stunned” won’t fire on “State.Stunned.Hard” with the exact variant.

An ability is gated by a GameplayTagQuery for State.Debuff. The character has State.Debuff.Poison — but the query returns false.

Hierarchical Tags

GameplayTags are hierarchical: State.Debuff.Poison is a child of State.Debuff. Whether a query matches a child depends on which check it uses.

HasTag vs HasTagExact

The same split exists for HasAny / HasAnyExact and HasAll / HasAllExact.

Tag Queries

FGameplayTagQuery built in the editor uses the non-exact match by default for “Match Tag”. If you authored it expecting exact behavior (or vice versa), it won’t do what you think — re-check each clause.

Register the Tags

Also confirm both tags actually exist in the Gameplay Tag table. A query against a tag that isn’t registered silently never matches.

Verifying

Apply State.Debuff.Poison; the “has any debuff” query fires. A query specifically for the exact parent tag doesn’t — as intended. Both behaviors are now deliberate.

“HasTag matches children; HasTagExact doesn’t. Choose per check — the hierarchy is the whole point of tags.”

Design your tag hierarchy so the non-exact match is usually what you want — that’s the idiomatic GAS pattern.