End-to-End Build: The Official Persistent Stats Tutorial and the Community Guides
Lesson 28 handed you the parts: the save table (weak_map), the persistable Blueprint class, and the "read old, build new" update routine. This page shows how the parts assemble into a whole machine — the full route of Epic's Persistent Player Statistics tutorial, plus two community guides covering leaderboards and quest counters. Follow along and you walk away with a publishable persistence system.
1. Walking the Official Tutorial: Four Puzzle Pieces, One System
Epic's tutorial "Persistent Player Statistics in UEFN" walks you step by step through a player stats system that persists across sessions (wins, rounds played, that kind of data), and its structure happens to string Lesson 28's concepts together in exactly the right order:
- ▢ Piece one: define the stats class. One "persistable Blueprint class" (class<final><persistable>), every field a constant with a default value — leaving the door open for future version evolution.
- ▢ Piece two: a module-level save table. Set up a weak_map with the player as the key and one copy of the stats class per slot, declare it outside every class (module scope), and persistence kicks in automatically.
- ▢ Piece three: initialize on join. When a player enters, run one Branch against the save table: a hit means a returning player; a miss means write a default instance into the table — "not found = new player", precisely that "does this path go through" intuition from the base lesson.
- ▢ Piece four: the update function. Fields are constants you can't edit, so every update is "read out the old instance → assemble a new one → swap the whole thing back with a Set"; the tutorial finishes by showing the data on in-game UI (for exactly which nodes/interfaces that UI part uses, defer to the original tutorial).
The skeleton of the core update function looks like this — you'll notice it's cut from the same mold as Lesson 28's visit counter, except each slot now stores a whole class instead of a single int:
# Piece one: a persistable stats class, every field with a default value
player_stats := class<final><persistable>:
Wins:int = 0
TotalRounds:int = 0
# Piece two: the persistent container at module scope
var PlayerStatsMap:weak_map(player, player_stats) = map{}
# Piece four: update = read old, build new, swap the whole thing
RecordWin(Player:player):void =
var NewStats:player_stats = player_stats{ Wins := 1, TotalRounds := 1 }
if (Old := PlayerStatsMap[Player]):
set NewStats = player_stats{ Wins := Old.Wins + 1, TotalRounds := Old.TotalRounds + 1 }
if (set PlayerStatsMap[Player] = NewStats) {}
Reading the code, Blueprint-style: RecordWin is the update logic that fires on "won a round" — first assemble a default new instance of "wins 1, total rounds 1" (covering the new-player case); then use a Branch to look up this player's old stats, and on a hit re-assemble the instance as "old wins +1, old total rounds +1"; finally use one Set to write the whole new instance back into the save table. It's the very same machine as the base lesson's visit counter — each slot just went from holding one number to holding a full stats sheet.
2. Community Add-Ons: Leaderboards and Quest Counters
The official tutorial covers the main quest line — "one player's own data" — and the community tutorials fill in two high-frequency variants. "Verse Persistence Series: A Comprehensive Guide" systematically covers the common combinations of persistence needs; its most valuable piece is the leaderboard approach: you can't walk a save table with a ForEach, so a "server-wide ranking" can't be fished straight out of save data — the standard pattern is to look up the save for each present player one by one, then sort them into an ordinary array for display within that match. "A Persistent Quest Counter in Verse Code" builds a cross-session quest counter, showing how "progress-type" data (how many times done, which step reached) gets designed into a small, sturdy persistable class.
Put the three resources together and you've covered the three most common product shapes for persistence: personal profiles (level, gold), scores and rankings (best score, wins), and progress (quests, unlocks).
3. A Suggested Learning Route
If you want to turn Lesson 28's knowledge into a genuinely shippable feature, take it in this order:
- Step one: rebuild Lesson 28's visit counter without peeking at the answer — write it yourself until it compiles.
- Step two: follow the official stats tutorial through a complete system, paying special attention to the "initialize on join" and "construct a new instance" stages.
- Step three: with the community guides as reference, reshape the stats class into whatever your own project needs (gold + level, or quest progress), publish a private version, and verify cross-session saving for real.
One last echo of Lesson 28's mantra: judge persistence by post-publish behavior (a private version is enough) — editor test sessions don't count.
In the official stats tutorial, a player wins a round and their player_stats (a persistable class) needs updating. Which pattern does it use?
Sources
This article draws on Epic's official documentation and community tutorials: