端到端实战:官方持久化统计教程与社区指南
第 28 课给了你零件:存档表(weak_map)、持久化蓝图类(persistable 类)、还有「读旧造新」的更新套路。这一页带你看零件怎么组装成整机——官方 Persistent Player Statistics 教程的完整路线,加上两篇社区指南覆盖排行榜与任务计数器,跟着做就能收获一套可发布的持久化系统。
一、官方教程走一遍:四块拼图拼成一个系统
官方教程《Persistent Player Statistics in UEFN》手把手实现一个跨会话保存的玩家统计系统(胜场、参与局数这类数据),它的结构恰好就是把第 28 课的知识点按顺序串了一遍:
- ▢ 拼图一:定义统计类。一个「持久化蓝图类」(class<final><persistable>),字段全是带默认值的常量——为将来的版本演化留好门。
- ▢ 拼图二:模块级存档表。建一张 weak_map,键是玩家(player)、每格放一份统计类,声明在所有类的外面(模块作用域),持久化就自动生效。
- ▢ 拼图三:进图初始化。玩家进场时用一个 Branch 去存档表里查一次:查到了说明是老玩家,查不到就往表里写一份默认实例——「查不到 = 新玩家」,正是基础课讲过的那种「这条线走不走得通」的直觉。
- ▢ 拼图四:更新函数。字段是常量改不了,所以每次更新都是「读出旧实例 → 拼一个新实例 → 用 Set 整个换回去」;教程最后还把数据显示到了游戏内 UI 上(UI 那部分具体用哪些节点/接口以教程原文为准)。
核心更新函数的骨架长这样——你会发现它和第 28 课的访问计数器几乎是一个模子,只是每格存的东西从一个 int 换成了一整个类:
# 拼图一:可持久化的统计类,字段全部带默认值
player_stats := class<final><persistable>:
Wins:int = 0
TotalRounds:int = 0
# 拼图二:模块作用域的持久化容器
var PlayerStatsMap:weak_map(player, player_stats) = map{}
# 拼图四:更新 = 读旧、造新、整个换掉
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) {}
读图翻译:RecordWin 就是「赢了一局」时跑的更新逻辑——先默认拼一份「胜场 1、总局数 1」的新实例(应对新玩家);再用一个 Branch 查这位玩家的旧统计,查到了就改成用「旧胜场 +1、旧总局数 +1」重新拼一份;最后用一个 Set 把这份新实例整个写回存档表。和基础课那台访问计数器一模一样,只是每格存的从一个数变成了一整份统计。
二、社区补充:排行榜与任务计数器
官方教程给了「一个玩家自己的数据」这条主线,社区教程补上两类高频变体。《Verse Persistence Series: A Comprehensive Guide》系统覆盖了持久化的常见需求组合,其中最有价值的是排行榜思路:存档表不能用 ForEach 遍历,所以「全服排行」没法直接从存档里捞出来——通用做法是对在场玩家逐个查存档,在这一局之内用一个普通数组把他们排好序再展示。《A Persistent Quest Counter in Verse Code》则做了一个跨会话的任务计数器,展示了「进度型」数据(做了几次、到哪一步)怎么设计成一个小而稳的持久化类。
三份材料合在一起,正好覆盖了持久化最常见的三种产品形态:个人档案(等级、金币)、成绩与排行(最好成绩、胜场)、进度(任务、解锁)。
三、建议的学习路线
如果你想把第 28 课的知识真正落地成可发布的功能,推荐这个顺序:
- 第一步:重做第 28 课的访问计数器,不看答案,自己写到编译通过。
- 第二步:跟着官方统计教程做一遍完整系统,重点体会「进图初始化」和「构造新实例」两个环节。
- 第三步:参考社区指南,把统计类改造成你自己项目需要的形态(金币 + 等级,或任务进度),发布一个私有版本,真实验证跨会话的数据保存。
最后提醒一句第 28 课的老话:验证持久化请以发布后(私有版本即可)的行为为准,编辑器测试会话不能作数。
官方统计教程里,玩家赢了一局,要更新他的 player_stats(persistable 类),用的是哪种模式?
来源
本文整理自 Epic 官方文档与社区教程: