GDKB

Operators

Beginner15 Minutes readUpdated July 21, 20261 related concept

An operator is a symbol that performs an operation on one or more values (its operands) and produces a result. `+`, `-`, `==`, `&&`, and `=` are all operators. Operators are how individual values combine into the larger computations that make up an expression — nearly every line of game logic is built from a handful of operators applied to variables and literals.

On this page

Operators

Summary

An operator is a symbol that performs an operation on one or more values (its operands) and produces a result. +, -, ==, &&, and = are all operators. Operators are how individual values combine into the larger computations that make up an expression — nearly every line of game logic is built from a handful of operators applied to variables and literals.

Mental Model

An operator is a small machine with input slots and one output slot. Feed it operands of the right type, and it produces a result of a (possibly different) type. 5 + 3 feeds two integers into + and gets an integer out; 5 > 3 feeds two integers into > and gets a boolean out — the input and output types need not match, and knowing what type an operator produces is as important as knowing what it accepts.

Operators chain: the output of one becomes the input of the next (a + b * c), which is why order — which machine runs first — has to be a fixed, learnable rule (precedence) rather than left to guesswork.

Core Explanation

Operators group by what they do:

  • Arithmetic — + - * / % operate on numbers. % (modulo) returns the remainder of division and is the standard tool for "wrap around every N" logic (cycling through an array, alternating frames).
  • Comparison / relational — == != < > <= >= compare two values and always produce a bool. == checks equality; critically, it is a different operator from = (assignment) even though they look similar.
  • Logical — && || ! combine or invert bool values: "both true", "either true", "the opposite". They are how multiple conditions combine into one (isGrounded && !isStunned).
  • Assignment — = stores a value into a variable. Compound forms (+= -= *= /=) combine an operation with assignment: health -= damage is shorthand for health = health - damage, doing both in one expression.
  • Increment / decrement — ++ and -- add or subtract one. The prefix (++x) and postfix (x++) forms both increment x, but differ in what value the expression itself evaluates to — prefix yields the new value, postfix yields the old one. This distinction only matters when the increment is used inside a larger expression, not on its own line.

Precedence and associativity decide the order operators apply in when an expression has more than one. Multiplication and division bind tighter than addition and subtraction (2 + 3 * 4 is 14, not 20) — the same rule taught in arithmetic class, extended to every operator the language defines. Parentheses override precedence explicitly, and are the recommended way to remove any doubt about evaluation order rather than relying on a reader to recall the full precedence table.

Short-circuit evaluation. && and || stop evaluating as soon as the overall result is already determined: in a && b, if a is false, b is never evaluated at all, because the whole expression must be false regardless. This is not just an optimization — code deliberately relies on it, e.g. enemy != null && enemy.IsAlive is safe specifically because a null enemy short-circuits before .IsAlive would run and throw.

Syntax / Examples

C# (Unity)

csharp
int total = 5 + 3 * 2;        // 11 — * before +
int remainder = 17 % 5;       // 2
bool canAct = isGrounded && !isStunned;
health -= damage;             // compound assignment
int next = index++;           // postfix: next = old index, index now +1

// Short-circuit — safe even when enemy is null
if (enemy != null && enemy.IsAlive) { /* ... */ }

C++ (Unreal)

cpp
int32 Total = 5 + 3 * 2;             // 11
int32 Remainder = 17 % 5;            // 2
bool bCanAct = bIsGrounded && !bIsStunned;
Health -= Damage;
int32 Next = Index++;

if (Enemy != nullptr && Enemy->IsAlive()) { /* ... */ }

Unreal Blueprint

Arithmetic and comparison operators are individual nodes (+, >, AND Boolean, NOT Boolean) wired between pins. There is no dedicated short-circuit node — AND Boolean in the visual graph evaluates both input pins before combining them, so the null-check-then-use pattern above must be expressed as a Branch node checking "Is Valid" first, not a single combined condition.

Practical Example

Deciding whether a jump input should be accepted combines several conditions with logical operators:

csharp
bool canJump = isGrounded && !isJumping && jumpCooldown <= 0f;
if (canJump && Input.GetButtonDown("Jump"))
{
    velocity.y = jumpForce;
    isJumping = true;
}

Each sub-condition is a comparison producing a bool; && combines them into one. Short-circuiting means jumpCooldown <= 0f is only checked if the character is actually grounded and not already jumping — cheaper, and it also means the expression's order can matter for readability even when it doesn't change the result.

Common Mistakes

  • = where == was meant. Covered in Variables, but worth repeating here because it is specifically an operator confusion: two operators that look almost identical do very different things.
  • Assuming &&/|| always evaluate both sides. Code that relies on a side effect happening inside the right-hand operand (isReady() && Log()) can silently skip that side effect when the left side short-circuits.
  • Operator precedence surprises, especially mixing && and || without parentheses: a || b && c is a || (b && c), not (a || b) && c, because && binds tighter than ||. Relying on memory of the full precedence table is fragile — parenthesize when combining more than one kind of logical operator.
  • Integer division inside a larger expression — total / count * 100 truncates before multiplying if both are integers, giving a different (and usually wrong) result than total * 100 / count.
  • Confusing prefix and postfix increment inside a larger expression (array[i++] vs array[++i]) — indexes a different element depending on which form is used, because the two forms produce different values for the surrounding expression even though both increment i.

Best Practices

  • Parenthesize any expression mixing more than one kind of operator (arithmetic with comparison, or && with ||) — it costs nothing and removes the need to recall precedence rules.
  • Order &&/|| operands so cheap, safety-establishing checks come first (enemy != null && enemy.IsAlive), deliberately relying on short-circuiting rather than fighting it.
  • Prefer compound assignment (x += n) over x = x + n — it states intent ("modify this variable") more directly.
  • Avoid combining an increment/decrement operator with another use of the same variable in one expression; split it into two statements instead.
  • Use % for any "wrap around" logic instead of hand-rolled conditional subtraction.

Exercises

  1. Evaluate 10 - 4 / 2 + 3 % 2 by hand using precedence rules, then verify with code.
  2. Write the jump-eligibility condition from the Practical Example using only if statements nested instead of &&, and compare readability.
  3. Demonstrate, with a small example, a case where a++ and ++a produce different observable results.
  4. Rewrite a || b && c with explicit parentheses matching how the language actually evaluates it, without changing behavior.
  • Variables and Data Types — operators only make sense in the context of the types they operate on.
  • Expressions — operators are the pieces expressions are built from.

References

Related Concepts