[UE5] Blueprint Variables Basics: Choosing Between Class Variables and Local Variables

Created: 2025-12-12Last updated: 2026-09-05

Values you remember, like HP, versus intermediate math used only inside a function. Explains Blueprint's Class Variable and Local Variable through scope and how long values persist, with a hands-on fix turning a total that goes 300 → 600 into 300 → 300.

Your Blueprint's Variables panel has HP, movement speed, and a running total from a calculation all lined up. As variables multiply, it gets hard to tell "values this Actor remembers" from "values used only once during a calculation."

Class Variables and Local Variables are what separate the two. Values you want to keep for later logic, like HP, are Class; intermediate math used only inside a function is Local. Both hold values, but they differ in the scope you can use them from and how long the value persists.

To see that difference, we call the same total calculation twice. We create a bug where the result goes 300 → 600 even though the array never changed, then fix it to 300 → 300.

A backpack for things you carry along, and a small note for use on the spot. An image of the two kinds of variable

What You'll Learn

  • Where you create Class Variables and Local Variables
  • The difference between "where can I use it" and "how long does the value last"
  • How to think about separating state from intermediate math
  • How to fix the bug where a previous value lingers when you call the same summation twice

Sponsored

Two kinds of variable: scope and lifetime

Class Variables are the ones you create under "Variables" in the My Blueprint panel. The HP and movement speed variables you normally use are these. Local Variables are created under "Local Variables," which appears when you open a function. They are used only inside that function.

The first thing to grasp is that Class Variables also hold separate values per Actor. Build Enemy A and Enemy B from the same enemy Blueprint and attacking Enemy A does not reduce Enemy B's HP.

One such object actually created from a Blueprint is called an instance. Class Variable here means "member variable," not a static variable shared by every instance of the class.

Where you can use it: scope

Scope is the range from which you can directly read and write that variable. For Enemy A's HP, both Enemy A's damage logic and its healing logic use the same value. A Local Variable created in a damage calculation function, meanwhile, is used only by that function.

Enemy A and Enemy B have separate HP. Enemy A's various logic uses the same HP, and the Local intermediate math lives inside the CalculateDamage function
ComparisonClass VariableLocal Variable
Where usable within the same BlueprintSeveral functions and eventsInside the function it was created in
After the function call endsThe value stays on that instanceNo intermediate value carries to the next call
Values it suitsHP, movement speed, current equipmentIn-progress totals, temporary calculation data

Handling a Class Variable from another Actor also involves a reference designating the target and settings for external access. It does not mean "usable unconditionally from any Actor." Here we compare within a single Actor.

How long the value lasts: lifetime

A Class Variable holds its value from the Actor's creation to its destruction, while a Local Variable is used per function call

A Class Variable remembers what earlier logic stored for as long as the Actor exists. Take damage and drop HP to 80, and the next healing operation starts from 80.

A Local Variable starts from its default value each time the function is called. The default is the starting value configured on that variable. Give a total's Integer variable a default of 0 and every call computes from 0. Even if the previous call left it at 300, that 300 does not carry over.

Note that a Class Variable's value lasts as long as that instance exists. That is separate from save data you keep after the game exits.

The basic rule: state is Class, intermediate math is Local

Asking "after this logic finishes, do I want to use this value in the next one?" makes the placement easy to decide.

State such as health and configuration goes in Class Variables, and in-function intermediate math goes in Local Variables

Values you remember, like HP, are Class

The player's CurrentHP decreases from attacks, increases from healing, and feeds the on-screen HP bar. Since it would be a problem if it reset to the initial value on every operation, it goes in a Class Variable.

Beyond current HP, settings such as max HP and movement speed, and a reference designating the equipped weapon, are also values the Actor remembers.

In-progress totals are Local

For example, a function computing the total score for a results screen adds 100, 100, and 100 in turn. The intermediate 100 and 200 are only needed during the calculation. The next time you start the same summation, you want to add from 0 again.

Make that in-progress total a Local Variable. The final 300 can be handed back to the caller as the function's return value. A return value says "this is the result of this work," and the caller does not need to read a variable inside the function directly.

Sponsored

What goes wrong if everything is a Class Variable

Holding intermediate math in a Class Variable is not automatically a bug. But it does require the following management.

  • Align the starting value each time. If the previous total lingers, reset it to 0 before calculating.
  • Track which logic wrote it. Using the same variable in another function widens the area you have to search when a value changes.
  • Distinguish state from intermediate math. Even as Variables multiply, keep it organized so you can find key values like HP.

For a calculation contained within a function, making it a Local Variable also narrows where you have to look to that function. In the hands-on next, we actually observe the first problem — the previous total lingering.

With a Class Variable the previous total lingers, but with a Local Variable you get the same result every time

Hands-On: fixing the bug where the second total is 600

Say you defeated three of the same enemy and earned 100 points each, and you compute the total. Compute it once or compute it again, the correct answer is 300 points.

The first run gives 300 but the second gives 600. Starting from the leftover previous total, it adds 100 three more times

1. Prepare the summing Actor and its variables

Choose Actor as the Blueprint Class parent and create BP_ScoreTester. Place exactly one in the level. This Actor has no visual, so confirm the placement in the Outliner.

Create these two under Variables in My Blueprint. Integer is the type for whole numbers.

Variable nameTypeDefaultWhere
ScoreArrayArray of Integer100, 100, 100Variables
TotalScoreInteger0Variables

An Array is a list of values of the same type in order. Set ScoreArray's type to Integer and choose Array in the container selector next to the type. After Compile, use "+" in the default value field to add three elements, all 100 (→ Array, Set, and Map Basics).

2. Create the function where the previous value lingers

Create CalculateTotalScore with the "+" under Functions. In the Details' Outputs, add an output named Total of type Integer. Since we specify the order of two calls with a white exec line, turn the function's "Pure" off.

Place a For Each Loop inside the function. It pulls array elements out one at a time. Use Loop Body for the per-element work and Completed for what happens after everything finishes.

Assemble it in this order. When you drag a variable into the graph, Get reads the value and Set writes it.

  1. Connect the function entry's white exec output to For Each Loop's exec input. Connect Get ScoreArray to Array.
  2. Place an Integer + node and connect For Each Loop's Array Element to A and Get TotalScore to B.
  3. Connect +'s result to Set TotalScore's value input. Connect Loop Body's white line to Set TotalScore too.
  4. Connect Completed's white line to the Return Node. Connect a separately placed Get TotalScore to the Return Node's Total.

Leave Set TotalScore's white output unconnected, which returns control to the loop. Connecting from Set to the Return Node ends the function after adding just the first element. The Completed side is what returns the total.

Loop Body proceeds into Set TotalScore, and Completed proceeds into the Return Node. The Total return value reads TotalScore after all elements are summed

Execution order and the addition are split across two diagrams. The For Each Loop's Array Element omitted in the upper diagram connects to the addition in the lower one. Rather than creating a separate "Array Element" node, use the value pin the loop provides.

Adding the For Each Loop's Array Element to the current TotalScore and passing the result to Set TotalScore. In the fix, the Get and Set are replaced with RunningTotal

3. Call the same function twice in a row

From Event BeginPlay in the Event Graph, place CalculateTotalScore and Print String alternating twice each, and connect the white lines in this order.

Event BeginPlay
  → CalculateTotalScore (1st) → Print String (1st result)
  → CalculateTotalScore (2nd) → Print String (2nd result)

Pass the first function's Total output to the first Print String. Put 1st: in Append's A and the Total converted to String in B, then connect Append's result to In String. The Integer-to-String conversion node is inserted when you connect the pins. Do the same for the second with 2nd: and the second Total.

Set Print String's Duration to 10 seconds, then Compile, save, and Play. Seeing 1st: 300 and 2nd: 600 means you reproduced the bug. New messages may appear above older ones, so read by the "1st" and "2nd" labels rather than by position (→ How to use Print String).

Since TotalScore is a Class Variable, the 300 stored on the first run remains. The second run adds 100 three more times on top of that 300, giving 600. The array did not grow.

4. Move the in-progress total to Local

Stop Play and open CalculateTotalScore. Create RunningTotal as an Integer under Local Variables in My Blueprint, and set its default to 0 after Compile.

Replace Set TotalScore inside the function with Set RunningTotal, and both Get TotalScore nodes with Get RunningTotal. ScoreArray, the addition, the loop, and the Return Node connections stay the same. Once the node replacement is done, delete the now-unused TotalScore from Variables.

Compile, save, and Play again, and you get 1st: 300 and 2nd: 300. RunningTotal starts from its default 0 on each call, so it does not inherit the previous total.

A Local Variable with default 0 sums onto a fresh note each call. With a Class Variable, the previous number lingers

Finally, change ScoreArray to 100, 200, 300. If both calls report 600, you are summing from the array each time rather than displaying a hard-coded 300.

Does resetting the Class Variable to 0 also fix it?

Yes. Placing Set TotalScore = 0 at the start of the original function also returns 300 every time. Here we chose a Local Variable that makes clear it is for this function's calculation, because no other logic uses the in-progress total.

The point is not to avoid Class but to decide placement based on whether the value needs to persist. If you want to use the final result later, the caller can store the return value in a Class Variable.

Sponsored

Bonus: Good to Know Up Front

When you want intermediate math in the Event Graph

The named Local Variables we used are created by opening a function. The Event Graph has no equivalent panel. Once the logic comes together, consider extracting it into a function.

That said, if you just add a value and pass it straight to the next pin, you can compute without a variable at all. There is no need to think "it is intermediate math, so I must add a Local" (→ The difference between Function and Macro).

Making one enemy tougher than the rest

Turn on "Instance Editable" on a Class Variable and you can change the value in the Details of an instance placed in the level. You can set Enemy A's MaxHP to 200 and Enemy B's to 100. That is the setting that lets you edit values per instance in the level.

Group variables by purpose as they grow

Setting Category in a variable's Details to something like Stats or Config classifies them within My Blueprint. On top of separating Class and Local, grouping your state and configuration variables makes them easier to find.

Summary: what to consider before creating a variable

What is this value for?How to choose
Something to remember for later, like HP or equipmentClass Variable
An in-progress total used only while one function runsLocal Variable
Handing a computed result back to the callerA function Output and the Return Node
Computing and passing straight onConnecting pins directly may need no variable at all

Class Variables remember state; Local Variables support that function's calculation. When results change from the second run on, as with the 300 → 600 here, check which value is still there when the calculation starts.

Ways to group logic are covered in The difference between Function and Macro, and organizing whole graphs in 10 techniques for organizing Blueprints.

Further Reading

Unreal Engine Notes in this section98