GameplayTag Condition

GameplayTagCondition is a single expression that asks a question about a collection. Is this tag present? Is this tag’s value above a threshold? Are these two tags equal in value? The condition evaluates against a live collection and produces a true or false answer. On its own it is a simple test. Combined with others, it becomes the building block for arbitrarily complex logic that lives entirely in data.

Conditions are what make tags useful beyond simple presence tracking. Rather than writing bespoke evaluation code every time a system needs to know whether something is in a particular state, you express the question as a condition and let the system answer it consistently wherever that condition appears.


Anatomy of a Condition #

Every condition has three parts: a tag to evaluate, a comparison operator, and a value to compare against.

The tag identifies which entry in the collection to look at. The comparison operator describes the relationship being tested. The value is what the tag’s current value is being compared to.

The comparison operators cover the full range of numeric relationships. Exists and NotExists ask only whether a tag is present or absent, without caring about the specific value. Equal and NotEqual check for an exact value match. Less, LessEqual, Greater, and GreaterEqual handle ordered comparisons for cases where magnitude matters, a health threshold, a stack count minimum, a charge level ceiling.


Exact Match and Hierarchy Awareness #

Like the collection’s query methods, a condition can operate in exact-match mode or hierarchy-aware mode.

In exact-match mode the condition looks only at the specific tag named. If the collection holds Effects.Debuff.Poison and the condition names Effects.Debuff, exact mode will not find it.

In hierarchy-aware mode the condition evaluates across the named tag and all of its registered descendants. If the collection holds multiple descendants, the evaluation uses the highest value found across all of them. This means a condition asking whether Effects.Debuff is greater than two will return true if any single debuff in the collection has a value of three, even if no others do.

This makes hierarchy-aware conditions useful for broad threshold checks. Rather than writing a separate condition for every debuff type, one condition on the parent tag catches the whole family.


Tag-vs-Tag Comparisons #

The right-hand side of a condition does not have to be a fixed value, and in some cases it does not need to be a numeric value at all. Two distinct patterns extend what conditions can express.

The first is a live numeric comparison. Rather than comparing a tag’s value against a constant, the comparison target can be drawn from the collection itself by nominating a second tag. The system reads that tag’s current value at evaluation time and uses it as the right-hand side. Is the character’s current health less than their maximum health? Is the number of active buffs equal to the number of debuffs? These comparisons adapt to whatever the collection holds at that moment, with no fixed numbers baked in.

The second pattern applies when a tag’s value is itself a tag, as in the tag-as-enumeration pattern described in the collection article. Here the value is not a number to compare arithmetically; it is an identity to compare relationally. Three operators exist specifically for this:

IsMemberOf asks whether the stored tag is a descendant of a given reference tag. A character whose Player.Class holds Classes.Melee.Warrior satisfies a condition asking whether Player.Class is a member of Classes.Melee. Add a new melee subclass later and any condition using IsMemberOf against Classes.Melee picks it up automatically.

IsParentOf is the inverse, asking whether the stored tag is an ancestor of the reference tag.

IsExactly asks whether the stored tag is precisely the reference tag, with no hierarchy involvement. This is the strict equality check for tag-identity comparisons, where a Warrior should not satisfy a condition that demands exactly a Berserker.

These two patterns, live numeric operands and relational tag-identity operators, cover the full range of state-to-state comparisons a condition system needs without requiring any custom evaluation code.


Combining Conditions #

A single condition is rarely the whole story. Most meaningful game logic involves multiple things being true simultaneously, or any one of several alternatives being true, or mutually exclusive states.

Multiple conditions combine using logical operators. And requires both sides to be true. Or requires at least one side to be true. Xor requires exactly one side to be true.

When more than two conditions are chained together the operators follow a defined precedence: And binds most tightly, then Or, then Xor. This mirrors the precedence rules most programmers already know from code, so the behaviour of a condition list is predictable without having to think carefully about evaluation order.

In practice this means you can express natural game logic directly. A condition chain might read as “stunned, and either has no mana or is silenced”. The And between stunned and the mana-or-silence group evaluates before the Or between the two alternatives, giving the right result without any explicit grouping.

An empty condition list always evaluates to true. This is a useful default, it means an operation or trigger with no conditions attached is unconditional, and adding conditions later to restrict it is purely additive.


Where Conditions Appear #

Conditions are evaluated against a collection, but they are not owned by one. A condition is a self-contained piece of data that can be stored anywhere and evaluated against any collection passed to it.

This makes them composable. A single condition or list of conditions can be attached to an operation to gate when that operation applies. It can drive a trigger that fires events when its result changes. It can be stored in a shared asset and referenced from multiple places across a project. The evaluation logic is always the same; only the collection being tested varies.

This separation between the condition definition and the collection it evaluates against is what makes conditions reusable across different objects and contexts without coupling them to any specific piece of game state.

Rate This Article!