เอกสาร Steamworks
สถิติและรางวัลความสำเร็จ

ภาพรวม

ระบบสถิติและรางวัลความสำเร็จของ Steam จะมอบวิธีการง่าย ๆ เพื่อให้เกมของคุณสามารถให้บริการการติดตามรางวัลความสำเร็จและสถิติที่บันทึกไว้ถาวรและใช้งานข้ามอุปกรณ์ได้สำหรับผู้ใช้ของคุณ โดยข้อมูลผู้ใช้จะเชื่อมโยงกับบัญชี Steam ของผู้ใช้เอง รวมทั้งสามารถจัดรูปแบบและแสดงผลรางวัลความสำเร็จและสถิติของผู้ใช้แต่ละรายในโปรไฟล์ชุมชน Steam ของผู้ใช้ได้

เอาไว้ใช้ประโยชน์อะไรได้บ้าง

นอกจากจะมอบรางวัลอันเลอค่าให้แก่ผู้เล่นเกมของคุณแล้วนั้น รางวัลความสำเร็จยังมีประโยชน์ในการกระตุ้นและสนับสนุนการเล่นเป็นทีมและการปฏิสัมพันธ์ระหว่างผู้เล่น ทำให้เป้าหมายของเกมมีมิติที่หลากหลายขึ้น และให้รางวัลผู้ใช้ผู้ทุ่มเทเวลาของตนเองให้กับการใช้เวลาเล่นเกม

ส่วนสถิตินั้นจะทำหน้าที่ติดตามข้อมูลที่มีรายละเอียดสูงต่าง ๆ เช่น เวลาเล่น จำนวนของพาวเวอร์อัปที่ใช้ และอื่น ๆ ซึ่งคุณยังสามารถเลือกได้ว่าใช้งานเพียงแค่ติดตามข้อมูลในเกมก็ได้ เช่น มอบรางวัลความสำเร็จโดยพิจารณาจากสถิติการเล่นเกมหลายเซสชันที่เก็บมาจากผู้ใช้ผ่านเครื่องคอมพิวเตอร์หลากหลายเครื่อง เป็นต้น

ภาพรวมการใช้งาน

นิยามสถิติและรางวัลความสำเร็จสำหรับเกมของคุณ

รางวัลความสำเร็จนั้นจะใช้งานได้เฉพาะกับแอปพลิเคชันของตัวเอง และสามารถตั้งค่าได้ที่หน้าผู้ดูแลแอปของเว็บไซต์พันธมิตร Steamworks

คุณสามารถจัดเก็บข้อมูลสถิติได้ 3 ประเภทด้วยกัน ได้แก่:
  • INT - จำนวนเต็ม 32 บิต (แบบมีเครื่องหมายบวกลบ) (เช่น จำนวนของเกมที่เล่นไป)
  • FLOAT - จำนวนแบบมีทศนิยม 32 บิต (เช่น จำนวนกิโลเมตรที่ได้ขับรถไป)
  • AVGRATE - ค่าเฉลี่ยเคลื่อนที่ กรุณาอ่าน: The AVGRATE stat type

เว็บไซต์พันธมิตร Steamworks จะเตรียมอินเตอร์เฟสสำหรับนิยามรายละเอียด พร้อมอัปเดตสถิติและรางวัลความสำเร็จของเกมของคุณ ซึ่งในการใช้งานนั้น คุณจะสามารถ:
  • นิยามรายละเอียดของสถิติและรางวัลความสำเร็จเบื้องต้น
  • เพิ่มสถิติและรางวัลความสำเร็จเพิ่มเติม
  • อัปเดตชื่อ คำอธิบาย และไอคอนของรางวัลความสำเร็จ
  • อัปเดตพารามิเตอร์และข้อจำกัดทางสถิติ (ค่าสูงสุด/ต่ำสุด ความกว้างค่าเฉลี่ยเคลื่อนที่ ฯลฯ)
สถิติจะประกอบไปด้วยคุณสมบัติดังต่อไปนี้:
  • ID - ไอดีตัวเลขที่สร้างให้แก่สถิติแต่ละค่าโดยอัตโนมัติ
  • Type - ประเภทข้อมูลของสถิติตัวนี้ - INT, FLOAT หรือ AVGRATE
  • API Name - สตริงที่ใช้เพื่อการเข้าถึงสถิตินี้โดยใช้ API
  • Set By - ตั้งค่าว่าจะให้ใครสามารถแก้ไขสถิติตัวนี้ได้ ซึ่งค่าเริ่มต้นคือ ไคลเอนต์ สำหรับข้อมูลเพิ่มเติม กรุณาอ่าน %3D%20#game_server_stats
  • Increment Only - หากใช้งาน สถิติตัวนี้จะมีค่าเพิ่มขึ้นได้อย่างเดียวเมื่อเวลาผ่านไป
  • Max Change - หากใช้งาน จะกำหนดขีดจำกัดการเปลี่ยนแปลงค่าสถิติสูงสุดที่เกิดขึ้นได้จากการเรียก SetStat ครั้งหนึ่งจนถึงการเรียก SetStat ครั้งต่อไป
  • Min Value - หากใช้งาน จะเป็นการกำหนดค่าตัวเลขต่ำสุดที่สถิติตัวนี้รองรับได้ ซึ่งค่าเริ่มต้นจะเป็นค่าต่ำสุดของประเภทข้อมูลตัวเลขที่ใช้ (INT_MIN หรือ -FLT_MAX)
  • Max Value - หากใช้งาน จะเป็นการกำหนดค่าตัวเลขสูงสุดที่สถิติตัวนี้รองรับได้ ซึ่งค่าเริ่มต้นจะเป็นค่าสูงสุดของประเภทข้อมูลตัวเลขที่ใช้ (INT_MIN หรือ -FLT_MAX)
  • Default Value - หากใช้งาน จะมีการกำหนดค่าเริ่มต้นให้กับสถิติตัวนี้แก่ผู้ใช้คนใหม่ หากไม่ใช้งาน ค่าเริ่มต้นจะมีค่าเป็น 0
  • Aggregated - หากใช้งาน Steam จะเก็บค่าผลรวมโดยรวมของสถิติตัวนี้ สำหรับข้อมูลเพิ่มเติม กรุณาดูที่หัวข้อค่าสถิติโดยรวมด้านล่าง
  • Display Name - ชื่อของค่าสถิตินี้เมื่อแสดงผลในแอปของคุณ
AVGRATE ค่าสถิติจะมีค่าคุณสมบัติเพิ่มเติมดังต่อไปนี้:
  • Window - ขนาดของ "ช่วงข้อมูล" ที่จะใช้ในการหาค่าเฉลี่ยข้อมูลของคุณ
ค่าสถิติ AVGRATE จะเป็นค่าที่เฉลี่ยโดยอัตโนมัติด้วย Steam กรุณาอ่าน AVGRATE ในส่วนด้านล่างเพื่อรับข้อมูลเพิ่มเติม

รางวัลความสำเร็จจะประกอบไปด้วยค่าคุณสมบัติต่อไปนี้:
  • ID - ไอดีตัวเลขที่สร้างให้แก่รางวัลความสำเร็จแต่ละค่าโดยอัตโนมัติ
  • API Name - สตริงที่ใช้เพื่อการเข้าถึงรางวัลความสำเร็จนี้โดยใช้ API
  • Progress Stat- กำหนดค่าสถิติที่จะใช้เป็นแถบความคืบหน้าของรางวัลความสำเร็จนี้ในชุมชน ซึ่งถ้าค่าสถิติมีค่าถึงจุดที่ปลดล็อคได้ รางวัลความสำเร็จก็จะปลดล็อคโดยอัตโนมัติ
  • Display Name - ชื่อที่กำหนดให้รางวัลความสำเร็จตัวนี้ ในการแจ้งเตือนแบบป็อปอัปของไคลเอนต์และในชุมชน สามารถแปลให้เป็นภาษาอื่น ๆ ได้
  • Description - คำอธิบายของรางวัลความสำเร็จตัวนี้ เอาไว้แสดงผลในชุมชน สามารถแปลให้เป็นภาษาอื่น ๆ ได้
  • Set By - ตั้งค่าว่าจะให้ใครสามารถปลดล็อครางวัลความสำเร็จตัวนี้ได้ ซึ่งค่าเริ่มต้นคือ ไคลเอนต์ สำหรับข้อมูลเพิ่มเติมดู %3D%20#game_server_stats
  • Hidden? - If true, a "hidden" achievement does not show up on a user's Community page (at all) until they have achieved it.
  • Achieved Icon - ไอคอนที่เอาไว้แสดงผลเวลาที่ได้รับรางวัลความสำเร็จแล้ว
  • Unachieved Icon - ไอคอนที่เอาไว้แสดงผลเวลาที่ยังไม่ได้รับรางวัลความสำเร็จ

รายละเอียดดังต่อไปนี้คือรายการของรางวัลความสำเร็จจาก แอปพลิเคชันตัวอย่างของ Steamworks API (SpaceWar):
achievements_spacewar.png

Special Considerations

  • Achievement names and icons should be all-ages appropriate.
  • By default, games are limited to 100 achievements at first. Once your app reaches the threshold for Profile Features, you will be able to add more achievements.

How to use them

การเข้าถึงสถิติและรางวัลความสำเร็จจากในเกมของคุณ:

The AVGRATE stat type

This type of stat provides some unique and very useful functionality, but it requires a little bit more detail to explain.

Consider the case where you'd like to track an average statistic, such as "Points earned per hour". One approach would be to have two stats, an INT "TotalPoints" and a FLOAT "TotalPlayTimeHours", and then divide points by time to get Points per Hour.

The downside to this implementation is that, once the player has accumulated a significant amount of playtime, the calculated average will change extremely slowly. In fact, the more the user plays the game, the less responsive that average will be. If the user has spent 100 hours playing the game, the calculated average will "lag" by about 50 hours of that. If they increase their skill, they will not see the increase in Points Per Hour that they expect.

The AVGRATE stat type lets you implement a "sliding window" effect on the average. For instance, you can utilize only the previous few hours of gameplay, so the statistic will more accurately reflect the player's current skill level.

Let's set up an AVGRATE stat to implement "points per hour" where only the previous 20 hours of gameplay affect the value. To do this, you would:
  • Note that, because the average will be "per hour", the time units on all time parameters associated with this stat will be "hours". This applies to the Window property on the stat itself, and also for the "dSessionLength" parameter passed in to UpdateAvgRateStat below.
  • Create an AVGRATE stat named "AvgPointsPerHour", and a Window property of 20.0 (remember, that's in "hours")
  • At appropriate points during your game, call ISteamUserStats::UpdateAvgRateStat with the following parameters:
    • pchName - "AvgPointsPerHour"
    • flCountThisSession - The number of points the player earned since the last call to UpdateAvgRateStat.
    • dSessionLength - The amount of game time since the last call to UpdateAvgRateStat. The unit should be the same as the unit on the stat's Window property. In this case, it is "hours".
  • For instance, if the player earned 77 points in the last round, which lasted 0.225 hours (13.5 minutes), that would be SteamUserStats()->UpdateAvgRateStat( "AvgPointsPerHour", 77, 0.225 )
In the above example, Steam will take the current rounds average of 342.2 points per hour ( 77 divided by 0.225 ) and blend it with the previous value. The result will reflect the total average over the player's last 20 hours of game time. If this were the first time the stat was updated for the current user, the current value would be 342.2.

This example uses "hours" as the time unit, but you may use whatever time unit you wish. Just keep in mind that you must consistently use that unit as your base for "dSessionLength", as well as the Window property.

Getting stats for other users

You can use ISteamUserStats::RequestUserStats to get the stats for another user. You can then use ISteamUserStats::GetUserStat, ISteamUserStats::GetUserAchievement, and ISteamUserStats::GetUserAchievementAndUnlockTime to get data for that user. This data is not updated automatically as the other user uploads new stats, so to refresh the data just call ISteamUserStats::RequestUserStats again.

To keep from using too much memory, a Least Recently Used (LRU) cache is maintained and other user's stats will occasionally be unloaded. When this happens a ISteamUserStats::UserStatsUnloaded_t callback is automatically sent. When this callback is sent then the specified user's stats will be unavailable until ISteamUserStats::RequestUserStats is called again.

Offline mode

Steam keeps a local cache of the stats and achievement data so that the APIs can be used as normal in offline mode. Any stats unable to be committed are saved for the next time the user is online. In the event that there have been modifications on more than one machine, Steam will automatically merge achievements and choose the set of stats that has had more progress. Because Steam keeps a local cache of stats data it is not necessary for the game to also keep a local cache of the data on disk. Such caches often come in conflict, and when they do it looks to users as if their progress has been reverted, which is a frustrating experience.

Game Server Stats

Parallel to ISteamUserStats is ISteamGameServerStats for game servers. These can get stats for users in the same way as clients can (described above). They can also set stats and award achievements, but only if "Set by" is set to GS (game server) or Official GS. The difference between game servers and official game servers is that official game servers are servers that you host and control. Using official game servers to set stats offers enhanced security against cheating, as users may be able to modify their own game servers or spoof being a game server. To define official game servers, enter the IP ranges of the servers here.

Stats and achievements that are settable by game servers cannot be set by clients. Game servers can only set stats and achievements for users currently playing on the server. If the user leaves the server there is a short grace period to set any final stats, but then any new uploads will be denied. This is to help ensure consistency and to avoid making it possible for a malicious game server to set anyone's stats at any time. Given the restriction, it is important not to wait until the end of a round to set stats. Set them continuously so you can store them as a user quits.

Clients will get automatic updates when a game server changes their stats. However, like clients, stats loaded by the server for other users are not refreshed automatically and can age out.

Resetting stats

During development, it is often the case that a complete wipe of stats and achievements on an account or all accounts is desirable for testing. To wipe stats for an account, call ISteamUserStats::ResetAllStats with bAchievementsToo set to true to wipe achievements as well. Once called remember to reiterate your stats and achievements and reset your in-memory game state. There is no way to globally wipe stats and achievements for all users. One of the reasons for this is that even if a global wipe were to be done, games in-progress may not notice the wipe and write back in-memory values. Fortunately, there is an easy way to build a global wipe system into your game. To do so:
  • Define a stat with a name like "Version"
  • Put a hardcoded stats version number in the game
  • Once stats have been loaded, compare the "Version" stat against your hardcoded version number
  • If they don't match, call ISteamUserStats::ResetAllStats and then set the "Version" stat to the hardcoded number.
This way, whenever you want a global wipe just change the hardcoded stats version number. The global wipe will then happen as people get the new build.

Stat consistency

It's a best practice to think about how related stats could become inconsistent. For instance, you may have three stats "GamesWon", "GamesLost", and "GamesPlayed". Despite the best of intentions, stats can and do get out of sync with each other. In this case, that could lead to games won and lost not adding up to the total of games played. If this was resolved by removing the "GamesLost" stat and instead computing it as "GamesPlayed" - "GamesWon", an inconsistency could cause "GamesLost" to be negative. In this case, it's best to drop the "GamesPlayed" stat and compute it as "GamesWon" + "GamesLost".

Global Stats

Stats can be marked as aggregated on the admin page to tell Steam to keep a global total of all users' values for the stat. This can be used to get data on total money in the economy, total kills, favorite weapons, favorite maps, and which team tends to do better. On the flip side, this should not be used for stats like "MostKills" as adding that up for multiple users would be meaningless. As stats are in the hands of users, this data is subject to being manipulated. Therefore it's crucial when using aggregated stats to set good bounds for min value, max value, increment only (if appropriate), and max change. Max change has a special meaning for aggregated stats. When a new value is uploaded, the global value will change no more than the max change value. This limits how quickly a cheater can influence the global totals.

To access the global totals, call ISteamUserStats::RequestGlobalStats and then ISteamUserStats::GetGlobalStat for each global stat. You can also ask for ISteamUserStats::RequestGlobalStats for a specified number of days of history. The history is the amount that stat changed every day. You can access that history with ISteamUserStats::GetGlobalStatHistory.

You can also request global achievement completion percentages from the client. To do so first call ISteamUserStats::RequestGlobalAchievementPercentages. Then, iterate the achievements in order of most completed to least completed by calling ISteamUserStats::GetMostAchievedAchievementInfo and ISteamUserStats::GetNextMostAchievedAchievementInfo. You can also get the completion percentage for a particular achievement by calling ISteamUserStats::GetAchievementAchievedPercent.

Testing


Before your app is released, you will not be able to see which achievements have been earned in the Steam Community or library. Your app will need a way to output what achievements have been earned for the user.

To clear an achievement or stats without adding code to your game, you can use the Steam client console. Run with steam.exe -console, then:
  • achievement_clear <appid> <achievement name>
  • reset_all_stats <appid>

The Steam Community

After your game has been released then information about individual and global achievement progress will be displayed in the Steam Community. Each player will have a link from their Community profile that goes to a page showcasing what they have achieved, and which they have yet to unlock.
หมายเหตุ: างวัลความสำเร็จของคุณจะไม่ปรากฏขึ้นจนกว่าจะสามารถมองเห็นแอปได้บ้างแล้วในชุมชน

Each achievement is listed with the appropriate icon, and the name and description as set in the Steamworks control panel. If the achievement name and description have been localized into the language the user has selected, then they will display in that language.

There will also be a link from this page, and one from your game's main Steam page, to a set of global achievement statistics for your game. It displays the percentage of Steam players of the game that have achieved each one, ordered from most common to the rarest achievement. This is fun for players to see, and also a great resource for you as a developer: are your special challenges hard enough? Or maybe too hard? (this information is also available on the Sales and Activations Reports site).

มีคำถามใด ๆ เพิ่มเติมหรือไม่?

Ask questions on the Stats and Achievements discussion board