[转载] Steam文档:统计与成就

[转载] 原文链接:https://partner.steamgames.com/doc/features/achievements

概览

Steam 统计和成就为您的游戏提供了一种简便的方式,持续并动态追踪用户的成就与统计数据。 用户的数据将与 Steam 帐户相关联,而每项成就与统计数据皆可依固定的格式显示于用户的 Steam 社区个人资料之中。

有什么好处

除了向您的游戏玩家提供高价值的奖励之外,成就也很适合用于鼓励和奖励团队合作或玩家互动、加深游戏目标的层次,并且玩家会因在游戏上花更多时间得到奖励。

统计数据则记录了许多精细的信息,像是游戏时间、使用的能量增强物品的数量等等。 您可将它们仅用于记录内部游戏数据,以便从多台电脑收集多重会话的游戏统计数据,为用户授予成就。

实现概览

定义游戏的统计与成就

成就专属于各个应用程序,必须使用 Steamworks 合作伙伴站点的应用管理页面进行设置。
您可直接从 此处 前往统计配置页面,或从 此处 前往成就配置页面。

可储存的统计类型有三种:

  • INT - 32 位(带正负号的)整数(例如游戏次数)

  • FLOAT - 32 位的浮点值(例如驾驶里程数)

  • AVGRATE - 移动平均数。 详见:AVGRATE 统计类型

Steamworks 合作伙伴站点的接口可供您定义和更新游戏统计和成就,具体用途为:

  • 定义初始统计与成就

  • 增加额外统计与成就

  • 更新成就名称、描述,和图标

  • 更新统计的参数与限制(最大 / 最小值、移动平均窗口大小等等)

统计具有下列属性:

  • ID - 每项统计自动产生的数字 ID

  • 类型 此项统计的类型 - INT 、 FLOAT ,或 AVGRATE

  • API 名称 - 用来访问此项成就的 API 字符串

  • 设置人- 设定谁能修改这项统计,默认为客户端。 更多信息请见 游戏服务器统计数据 文档。

  • 仅限增量– 设置后,此统计数值便只能随着时间增加

  • 最大变更- 设置后,每次调用一个 SetStat 到下一个 Setstat 时,此项统计的数值能改变的最大值

  • 最小值- 设置后,此项成就能接受的最小数值,默认最小值是基本数值类型的最小值( INT_MIN 或 -FLT_MAX )。

  • 最大值- 设置后,此项成就能接受的最大数值,默认最大值是基本数值类型的最大值( INT_MAX 或 FLT_MAX )。

  • 默认值- 设置后,新用户初始设置的默认统计数值。 如果没有设置,默认值则为零。

  • 合计– 设置后, Steam 将记录此项统计的全球统计。 更多信息,请见下方的全球统计。

  • 显示名称- 显示于 Steam 社区的统计名称。 可本地化。

AVGRATE 具有以下额外的属性:

  • 窗口 - 用来计算平均值的”滑动窗口”的大小

AVGRATE 统计由 Steam 自动平均得出。 请参见下文的的 AVGRATE 一节,了解更多信息。

成就具有下列属性:

  • ID - 每项统计自动产生的数字 ID

  • API 名称- 用来访问此项成就的 API 字符串

  • 进度状态- 指定一项统计数据,作为此项成就在社区中的显示进度指示器。 当统计数值达到解锁值时,成就将自动解锁

  • 显示名称- 出现于客户端弹出通知和社区的显示名称。 可本地化

  • **描述 **- 社区中关于此项成就的描述。 可本地化

  • 设置人- 设定谁能解锁此项成就。 默认是客户。 请参见 游戏服务器统计数据 ,了解更多信息。

  • 隐藏- 如勾选,”隐藏”成就在达成之前则完全不会显示于用户的社区页面中

  • 已达成图标- 达成成就后显示的图标

  • 未达成图标- 未达成成就时显示的图标

以下是 Steamworks API 示例应用程序(SpaceWar) 的成就列表:

achievements_spacewar.png

使用方法

在游戏中访问统计和成就:

AVGRATE 统计类型

此统计类型提供了独特且非常有用的功能,但需要一些详细说明。

假如您想追踪某项平均统计数据,例如”每小时平均得分”。 一种办法是设置两项统计数据,一个 INT 的”总得分”,和 FLOAT 的”总游玩时数”,然后将得分除以游玩时数,得到每小时平均得分。

这个方法这的缺点是,一但玩家的游戏时数达到某个程度,计算出的平均值将变动得非常缓慢。 实际上,玩家玩得越多,平均值的反应就越不明显。 如果玩家花了 100 个小时在游戏上,得出的平均将会”延迟”大概 50 个小时。 即便他们提高了技术水平,也不会如期看到每小时平均得分的增加。

AVGRATE 统计类型则能让您设置一个可影响平均值的”滑动窗口”。 举例来说,您可使用几小时前的游戏时间数据,让统计数值更精确地反应玩家目前的技术水平。

现在来设置一个 AVGRATE 统计来实现”每小时平均得分”,而且只有过去 20 个小时的游戏才能影响数值。 方法是:

  • 由于平均值以”每小时”计算,与此统计相关的时间参数的单位都是”小时”,例如统计本身的窗口属性,和传给 UpdateAvgRateStat 的 dSessionLength 参数

  • 创建一个名为” AvgPointsPerHour ”的 AVGRATE 统计,并将窗口属性设置为 20.0 (谨记:以”小时”为单位)

  • 在游戏中适当的时候,调用 ISteamUserStats::UpdateAvgRateStat 并传入下列参数:

    • pchName – ” AvgPointsPerHour ”

    • flCountThisSession - 自从上次调用 UpdateAvgRateStat 后,玩家所获得的分数

    • dSessionLength - 自从上次调用 UpdateAvgRateStat 后,玩家的游玩时数必须使用与窗口属性相同的单位,在此例中,以”小时”为单位。

  • 例如,玩家在过去 0.225 小时( 13.5 分钟)获得了 77 分,就会变成 SteamUserStats()-> UpdateAvgRateStat( " AvgPointsPerHour", 77, 0.225 )

在上述实例中, Steam 会将这回合的平均每小时 342.2 分( 77 除以 0.225 )与先前的数值一起计算,结果便是玩家过去 20 个小时游戏时间的平均得分。 如果这是第一次为此玩家更新数据,那么目前的值就是 342.2。

此实例用”小时”作为单位,但您也可使用任何其他的时间单位。请记住,您必须始终使用该单位作为”dSessionLength”的基础,以及窗口属性。

取得其他玩家的统计数据

您可使用 ISteamUserStats::RequestUserStats 取得其他玩家的统计数据,然后使用 ISteamUserStats::GetUserStatISteamUserStats::GetUserAchievement ,和ISteamUserStats::GetUserAchievementAndUnlockTime 取得用户的其他数据。 由于其他玩家会不断上传新的统计数据,您取得的数据并不会自动更新。 再次调用 ISteamUserStats::RequestUserStats 即可刷新数据。

为避免使用过多的内存,系统会维持一个近来最少使用( LRU )缓存,并会偶尔加载其他用户的统计。 这种状况发生时将自动发送一个 ISteamUserStats::UserStatsUnloaded_t 回调。 发出回调后,再次调用ISteamUserStats::RequestUserStats 之前,都无法使用该用户的统计数据。

离线模式

Steam 会将统计与成就数据保存于本机缓存之中,以便在离线模式中也能正常使用 API 。 这段时间无法上传的统计皆会被保存至下次联机至网络。 如在多台机器上都有过修改,Steam 会自动合并成就,并选择进度最多的一组统计数据。 由于 Steam 已经在本机缓存上保存了统计数据,游戏便没有必要再将数据缓存于磁盘上。 这两种缓存常常互相冲突,当他们这样做时,用户就会认为他们的进度已经复原了。

游戏服务器统计数据

ISteamUserStats 性质相近的便是游戏服务器的 ISteamGameServerStats 了,可以使用与客户端相同的方式取得用户的统计数据。 但只有在”设定人”是 GS(游戏服务器)或Official GS (官方游戏服务器)的情况下,才可以用它来设置统计和成就。 游戏服务器和官方游戏服务器的差别在于,官方服务器是您自己主持并控制的。 使用官方服务器设定统计数据能够杜绝作弊行为,因为如此一来玩家便无法变更自己的游戏服务器,或假扮游戏服务器。 如要设置官方服务器,可从此处输入服务器的 IP 范围。

游戏服务器可设定的统计与成就不能由客户端更改。 游戏服务器只能为正在服务器上游玩的玩家设定统计与成就。 当用户离开了服务器,会有一小段宽限期可设置最终的统计,之后所有上传都会被拒绝。 这是为了保持数据的一致性,以及避免恶意的服务器随时随意更改任何人的统计。 鉴于这项限制,尽量不要等到回合结束时才设置统计。 要持续地设置统计,当用户退出游戏时便能顺利储存。

游戏服务器变更统计时,客户端便会自动获得更新。 但是,像客户端一样,加载其他用户的数据后不会自动更新,有可能不正确。

重设统计数据

开发过程中,常常会有为了测试希望清除某个帐户所有统计与成就的状况。 要清除帐户所有统计,调用 ISteamUserStats::ResetAllStats,而将 bAchievementsToo 设置为 **true[/ b] 即可一同清除成就。 调用后,记得要重新逐一查看统计与成就,并重设内存中游戏状态。 无法统一清除所有用户的统计与成就。 这是因为就算统一清除了数据,运行中的游戏可能也不会注意到这次清除,而写入内存中的值。 所幸有一个简单的办法,可以在您的游戏中建立一个统一清除系统。 具体方法是:

  • 定义一项成就,名称可以用” Versoin ”

  • 在游戏中放入一个硬编码统计版本编号

  • 加载统计后,对比” Version ”和硬编码的版本编号

  • 如不相符,调用 ISteamUserStats::ResetAllStats 然后将”Version”设为硬编码号码

这样一来,无论何时您想要统一清除,只需改变硬编码的统计版本号码就可以了。 其他人拿到新生成版本时,便会统一清除数据。只需确保统一清除代码不会在最终生成版本中出现。

统计一致性

最好的做法是考虑相关的统计数据会如何变得不一致。 举例来说,您有三项统计”GamesWon”、”GamesLost”,和“GamesPlayed”。 即使考虑得再周到,统计数据之间也会确实出现无法同步的情况。此种情况下,胜场和败场数加起来有可能不到总游戏场数。 假如您将“GamesLost”去掉,而使用“GamesPlayed”-“GamesWon”来计算败场的话,数据不一致时便会导致”GamesLost”变成负数。 这种状况下,最好的办法是不要使用“GamesPlays”而使用 “GamesWon”+ “GamesLost”进行计算。

全球统计数据

可在管理页面中标出统计的合计, Steam 便会保存所有用户的该项统计的总值。 这可以用来记录经济体中所有的金钱、总击杀数、最受欢迎的武器或地图,或哪个队伍的表现更佳。 另一方面,此方法不能用在像是“MostKills”的统计中,因为将多个用户的最高击杀数加起来没有任何意义。 由于统计是掌握在玩家手上,这些数据便有遭到操纵的可能。 因此,使用合计时,设置最小值、最大值、仅限增量(如有需要)与最大变更便至关重要。 最大变更对合计统计来说意义特殊。 每当上传了新的值,合计值的改变不会超过最大变更值。 如此便能限制一个作弊者影响全球总数的快慢。

要访问全球统计,先调用 ISteamUserStats::RequestGlobalStats 然后再调用 ISteamUserStats::GetGlobalStat 取得每项统计。 也可向 ISteamUserStats::RequestGlobalStats 要求一段特定时间内的历史记录,这些历史记录了这项统计每天的变更量。 使用 ISteamUserStats::GetGlobalStatHistory 便可访问历史纪录。

您也可从客户端要求全球成就完成百分比。 首先调用 ISteamUserStats::RequestGlobalAchievementPercentages。 然后调用 ISteamUserStats::GetMostAchievedAchievementInfoISteamUserStats::GetNextMostAchievedAchievementInfo 以最多完成到最少完成的顺序逐一查看每项成就。 您也可调用 ISteamUserStats::GetAchievementAchievedPercent 取得某项成就的完成百分比。

Steam 社区

游戏发行之后,有关个人与全球的成就进度便会显示于 Steam 社区中。每个玩家都将从他们的社区资料中获得一个链接,此链接会显示他们已经取得的成就,以及他们还未解锁的内容。

备注:在您的应用在社区曝光以前,您的成就不会显示出来。

每项成就都会与在 Steamworks 控制面板中设置的图标、名称和描述一起列出。 如果成就的名称和内容已被本地化为用户所选语言,便会以该语言显示。

此页面和游戏的 Steam 主页面皆会有一个链接连至全球成就统计数据的页面,显示每一项成就的 Steam 玩家全球达标率,按最常见到最罕见的顺序排列。 这对于玩家来说很有趣,对开发者来说也是项很有用的资源;特别挑战够不够难? 或是难度太高了? (这些信息也可在 Steamworks 合作伙伴站点上找到)。**

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容