Docs/Core concepts/State & persistence
State & persistence
Everything your rules remember — coins, inventories, current phase — is state. Some survives disconnects, some resets every round. Choosing right matters.
Last updated 2026-06-06
Three kinds of state
- Live state — Variables you read/write. Coins, level, current_zone.
- Container state — Inventories holding items. Backpack, hotbar.
- Phase state — Which named stage the game is in. Lobby, game, ending. Always exactly one current phase per device.
Configs and Messages are not state — Configs are tweakable constants set in UEFN editor, Messages are fixed text. They never change at runtime.
Persistence
Per-player variables with Persist on survive disconnects and rejoins. When the player comes back next session, their value is restored. Without persistence, the value resets to Default every time they join.
💡 Tip
persistable class and accessor helpers — you don't see any of that, you just tick the box.- Persist ON — progression. Coins, level, XP, prestige.
- Persist OFF — temporary state.
kill_count(resets each round),current_zone,boss_spawned.
Scope: per-player vs. global
Every variable belongs to one of two scopes:
player— each player has their own copy. Use for stats, inventory, quest progress.global— one shared value across the whole island. Use for round number, wave count, boss spawned flag.
Patterns
Player progression
Currency + level + XP, all per-player, all persistent. Use increment_variable on earn events and compare_variable in IF for level-up gates.
Round counters
Per-player without persistence — kill_count, damage_taken. Reset to 0 on the round-start event via set_variable.
Global flag
boss_spawned (bool, global, persist OFF) — one rule sets it to true on spawn, other rules read it to gate behavior. Resets every round.
Gotchas
⚠️ Watch out
⚠️ Watch out
coins would be shared by everyone — they'd all spend the same wallet. This is the most common scope mistake.📌 Note
What gets generated?
Per-player persistent state compiles to a persistable player-data class with typed fields, plus get/set helpers on the device. Round-only state stays in a regular weak_map. Global state becomes a plain device field with a default value.
# Persistent per-player
te_player_stats := class<final><persistable>:
Version:int = 0
Coins:int = 0
Level:int = 1
# Round-only per-player
PlayerKills:weak_map(agent, int) = map{}
# Global
var BossSpawned:logic = false
See also