無所属

ホーム ドキュメントとヘルプ
Steamworks ドキュメンテーション
データと実績

新バージョンを英語でお読みいただけます

翻訳が公開されてから、このページの英語版が更新されました。このページの英語版を表示するにはこちらをクリックしてください。

概要

Steam のデータおよび実績を使用すると、ゲームにおけるユーザーの実績や統計データの永続的な追跡や管理を容易に行うことができます。Steam アカウントと関連づけられたユーザーのデータや、個々のユーザーの実績およびデータは、フォーマットを調えられ Steam のコミュニティプロフィールに表示されます。

利点

プレイヤーに価値のある報酬を付与する以外にも、実績はチームワークとプレイヤー同士の対話を奨励し、ゲームの目的に深みを与え、ゲーム内で時間を過ごすことに対して満足感を提供できます。
データはプレイ時間、パワーアップ使用回数など、きめ細かい情報を追跡します。あるいは、ゲームの内部データに絞って追跡させることもできます。そうすることで、たとえばユーザーの複数のコンピューターから収集されるマルチセッションのゲームプレイのデータに基づいて、実績を付与するというようなことも可能です。

実装概要

ゲームデータと実績の定義付け

実績はアプリケーション固有で、Steamworks パートナーサイトの「アプリ管理」ページで設定します。
データ設定ページへは、こちらから、そして実績の設定ページへは、こちらのリンクでアクセスできます。

ゲームでは保 3 種類のデータを存可能です:
  • INT - 32ビットの符号付き整数 (例、プレイしたゲーム数)
  • FLOAT - 32ビットの浮動小数点値 (例、運転した距離)
  • AVGRATE - 移動平均。次のドキュメントを参照: AVGRATE データタイプ
    Steamworks のパートナーウェブサイトは、ゲームのデータと実績を定義しアップデートするためのインターフェイスを提供します。これを利用することで、以下が可能になります:
  • 初期の統計データと実績の定義
  • 統計データと実績の追加
  • 実績の名称、説明、アイコンのアップデート
  • データパラメーターと制約 (最大 / 最小値、画面サイズの移動平均など) のアップデート
    データには、次のプロパティが用意されています:
  • ID - 各データ用に自動的に生成される数値 ID
  • Type - このデータの種類 – INT、FLOAT、または AVGRATE
  • API Name - API を使って、このデータにアクセスするために使用される文字列
  • Set By - データを修正できる人を設定。初期値は、クライアントに設定されています。詳細については、 ゲームサーバー統計データを参照してください。
  • Increment Only - データは時間と共に増加することのみが可能になります。
  • Max Change – 1 つの SetStat コールから次のコールまでに変更できるデータ値の限度を設定します。
  • Min Value - このデータが受け入れる最小値を表します。初期値では、最小値は基となる数値タイプの最小値になります (INT_MIN、または FLT_MAX)。
  • Max Value - このデータが受け入れる最大値を表します。初期値では、最大値は基本的な数値タイプの最大値になります (INT_MAX、または FLT_MAX)。
  • Default Value - 新規ユーザー用に最初に設定される初期値。設定されない場合、初期値はゼロになります。
  • Aggregated - Steam はこのデータのグローバル合計を保持します。詳細については、以下のグローバルデータを参照してください。
  • Display Name - Steam コミュニティに表示されるデータの名称です。ローカライズ可。
    AVGRATE データには、以下の追加プロパティがあります:
  • Window - データの平均化に使用される「スライディングウィンドウ」のサイズ
    An AVGRATE は Steam により自動的に平均化されるデータです。詳細は、以下のAVGRATE セクションを参照してください。

    実績には、次のようなプロパティが用意されています:
  • ID - 各データ用に自動的に生成される数値 ID
  • API Name - API で実績にアクセスするために使用される文字列
  • Progress Stat - コミュニティ上でプログレスバーとして使用される実績データを指定する。データがアンロック値に達すると、実績も自動的にアンロックされます。
  • Display Name - クライアントの通知ポップアップやコミュニティで表示される実績の名前です。ローカライズ可。
  • Description – コミュニティで表示される実績の説明です。ローカライズ可。
  • Set By - 実績をアンロックできる人を設定。初期値は、クライアントに設定されています。詳細は、 ゲームサーバー統計データを参照してください。
  • Hidden - true の場合、「非表示」の実績は、達成するまでユーザーのコミュニティ ページ上に全く表示されません。
  • Achieved Icon - 達成時に表示されるアイコン
  • Unachieved Icon - 未達成時に表示されるアイコン
    以下、Steamworks API Example Application (SpaceWar)からの実績のリストです:

    使用方法

    ゲーム内からの統計と実績へのアクセス:

  • Steamworks API の初期化後、ISteamUserStats に含まれるStats および Achievements API の使用を開始できます。
  • ゲーム セッションの開始時に ISteamUserStats::RequestCurrentStats を呼び出し、Steam のバックエンドからユーザーの統計データおよび実績を取得します。データの準備ができたら、ISteamUserStats::UserStatsReceived_t コールバックを受信します。
  • ISteamUserStats::GetStat および ISteamUserStats::GetAchievement を使用して、データの反復処理を行い、ゲームの状態を初期化します。
  • ゲーム内で実績を表示するには、ISteamUserStats::GetAchievementDisplayAttribute を使用して、名前 (「名前」) や説明 (「説明」) を含む、ユーザーが読める実績のプロパティデータを取得します。これらのプロパティは、Steamworks パートナーのウェブサイト上の、こちらでローカライズでき、返送されるデータはユーザーがゲームを実行している言語によって異なります。さらに、ISteamUserStats::GetAchievementIcon または、ISteamUserStats::GetAchievementAndUnlockTime でアンロックされた各実績の時間を使用してで実績のアイコンを取得することができます。
  • データの変更時、特にユーザーに表示されるデータの変更があった場合には、ISteamUserStats::SetStat または ISteamUserStats::UpdateAvgRateStat を呼び出してください。この呼び出しは、Steam の内部メモリー状態だけを変更するもので、コストはかかりません。これにより、ゲームがクラッシュしたとしても Steam はセッション間で変更を維持することができます。
  • ゲーム内の適切なポイント (チェックポイント、レベル遷移時など) に ISteamUserStats::StoreStats を呼び出し、変更をアップロードします。完了すると、ISteamUserStats::UserStatsStored_t コールバックを受信します。
  • プログレスバーを持つ実績には、進行状況のある特定の地点においてのポップアップ表示のために ISteamUserStats::IndicateAchievementProgress を使用してください。たとえば、20勝する必要がある場合に 10 回勝った時点で半分達成したことをユーザーに示す呼び出しに使うことができます。
  • 1 つ以上の実績がアンロックされた際には、それぞれのアンロックされた実績に対して ISteamUserStats::SetAchievement を呼び出し、次に実績をただちにアップロードするために ISteamUserStats::StoreStats を呼び出します。ゲームは ISteamUserStats::UserStatsStored_t コールバックに加え、アンロックされた個々の実績に対して 1 つの ISteamUserStats::UserAchievementStored_t コールバックを取得します。その際、Steam のゲームオーバーレイはユーザーに通知パネルを表示します。

    AVGRATE データタイプ

    このタイプの統計データはユニークで非常に便利な機能をいくつか提供しますが、多少説明が必要です。以下、詳細な説明です。

    「1 時間ごとに獲得するポイント」など、データの平均を追跡したい場合を考えてみましょう。1 つの方法としては、INT "TotalPoints" と FLOAT"TotalPlayTimeHours" の 2 つのデータを用意し、得点を時間で除算し、1 時間あたりの得点を算出する方法があります。

    この実装の欠点は、プレイヤーがかなりの時間をゲームに費やしていると、平均値の算出が極端に遅くなることです。実際、プレイヤーがゲームをすればするほど、平均値の変化が少なくなります。たとえば、ユーザーがゲームに 100 時間を費やした場合、算出される平均値は 50 時間ほど遅れる事となります。プレイヤーの技術が向上しても、 1 時間当たりの得点は期待するほど変化しないことになります。

    AVGRATE データタイプを利用すれば、平均値上に「スライディングウィンドウ」効果を実装できます。たとえば、ゲームプレイにおける最も最近の数時間だけを使用することで、データはより正確にプレイヤーの現在のスキルレベルを反映したものになります。

    では、AVGRATE データを設定して、過去 20 時間のゲームプレイだけが値に反映される「1 時間当たりのポイント」を実装してみましょう。そのためには、以下を実行します:
  • 平均値は「1時間ごと」になるため、このデータに関連する時間のパラメーターはすべて「時間」単位になる点にご注意ください。これは、データ自体のウィンドウプロパティと以下の UpdateAvgRateStat に渡される「dSessionLength」パラメーターにも適用されます。
  • 「AvgPointsPerHour」という名前の AVGRATE 統計データと、20.0 (単位は「時間」) というウィンドウプロパティを作成します。
  • ゲーム中の適切な時点で、以下のパラメーターと共に ISteamUserStats::UpdateAvgRateStat を呼び出します:
  • pchName - 「AvgPointsPerHour」
  • flCountThisSession - UpdateAvgRateStat への最終呼び出し以降に、プレイヤーが獲得したポイント数
  • dSessionLength – UpdateAvgRateStat への最終呼び出し以降のゲーム時間。この単位は、統計データのウィンドウプロパティ上の単位と同じものになります。この場合、その単位は「時間 (hour) 」です。
  • たとえば、プレイヤーが0.225 (13.5分) 時間の最終ラウンドで、77 点獲得したとします。その場合は、SteamUserStats()->UpdateAvgRateStat( "AvgPointsPerHour", 77, 0.225 ) となります。
    上記の例では、Steam は現在のラウンドの平均得点を、1 時間当たり 342.2 点 (77 を 0.225 で割った数) と算出し、過去の値と合わせます。結果は、プレイヤーの過去 20 時間のゲーム時間の総平均を反映します。これが現在のユーザーについての初めてデータの更新であった場合、現在の値は 342.2 となります。

    この例は「時間 (hours)」を時間単位として用いていますが、ご希望によってお好きな時間単位を設定することができます。ただし、「dSessionLength」とウィンドウプロパティの基準として、その単位を一貫して用いる必要があることを覚えておいてください。

    他のユーザーのデータの取得

    ISteamUserStats::RequestUserStats を使用して、別のユーザーの統計データを取得することができます。次に ISteamUserStats::GetUserStatISteamUserStats::GetUserAchievement、および ISteamUserStats::GetUserAchievementAndUnlockTime を使用して、そのユーザーのデータを取得します。他のユーザーが新たなデータをアップロードしたとしても、このデータは自動的にアップデートされません。データを更新するには、ISteamUserStats::RequestUserStats を再度呼び出してください。

    メモリを使いすぎないよう、使用頻度が少ない LRU (Least Recently Used) キャッシュが 1
    つ保持され、他のユーザーの統計データは時折アンロードされます。それが実行されると、ISteamUserStats::UserStatsUnloaded_t コールバックが自動的に送信されます。このコールバックが送信されると、ISteamUserStats::RequestUserStats が再び呼び出されるまで、指定されたユーザーの統計データは入手できません。

    オフラインモード

    Steam はオフラインモードでも API が正常に機能できるように、データと実績データのローカルキャッシュを保存します。コミットできないデータは、次にユーザーがオンラインになった時のために保存されます。1 つ以上のマシンから変更があった場合、Steam は自動的に実績を統合し、より進行している方のデータセットを選択します。Steam がデータのローカルキャッシュを保存しているため、ゲームがディスク上にあるデータのローカルキャッシュを保存する必要はありません。そういったキャッシュはしばしば競合を起こし、ユーザーから見るとゲームの進行状況が巻き戻されたように見え、ユーザーのフラストレーションの原因となることがあります。

    ゲームサーバー統計データ

    ISteamUserStats と並行してゲームサーバー用の ISteamGameServerStats があります。これらによってクライアントと同じ方法 (上記を参照) でユーザーの統計データを取得できます。データの設定および実績の付与を実行することもできますが、それは 「Set by」が GS (ゲームサーバー) または公式 GS に設定された場合のみ可能です。ゲームサーバーと公式ゲームサーバー間の違いは、公式ゲームサーバーがあなたがホストおよび管理するサーバーであるという点です。公式ゲームサーバーを使用して統計データを設定すれば、ユーザー運営のゲームサーバーでの修正(ハッキング)やゲームサーバーへのなりすましによるチート対策を施すことができセキュリティを強化できます。公式ゲームサーバーを定義するには、こちらでサーバーがホストされている IP 範囲を入力してください。

    ゲームサーバーが設定可能なデータと実績は、クライアント側では設定できません。ゲームサーバーは現在サーバー上でプレイしているユーザーに対してのみ統計データと実績を設定可能です。ユーザーがサーバーを離れた際には最終的なデータを設定するための短い猶予期間が設けられますが、その後はいかなる新規のアップロードも拒否されます。これにより統計データの一貫性が確保でき、悪意のあるゲームサーバーにユーザーの統計データを設定させないようにします。制限があるので、ラウンドの終わりまで統計データの設定を待たないほうがいいでしょう。継続的に設定し、ユーザーが終了すると同時に保存するようにしましょう。

    クライアントはゲームサーバーが統計データを変更した際には自動的にアップデートを受信します。ただし、クライアントと同様、他のユーザー用にサーバーがロードした統計データは自動的に更新されず、データが古い場合があります。

    統計データの再設定

    開発中には、テストのために 1 つのアカウント、またはすべてのアカウントの統計データや実績を完全に消去しなければならない場合があります。実績も含めアカウントの統計データをすべて消去するには、bAchievementsTootrue に設定して、ISteamUserStats::ResetAllStats を呼び出してください。呼び出しが完了したら、統計データと実績に対して反復処理を行い、メモリ内のゲーム状態を必ずリセットしてください。ユーザー全員の統計データと実績を一括消去する方法はありません。その理由の 1 つは、一括消去を実行しても、実行中のゲームはその消去に気付かず、メモリ内の値を書き戻すかもしれないためです。幸いにも、ゲーム内に一括消去システムを構築する簡単な方法があります。そのためには以下を実行してください:
  • 「バージョン」などのような名前で統計データを定義します
  • ゲーム内にハードコードされた統計データのバージョン番号を設置します
  • データがロードされたら、「バージョン」の統計データと、ハードコードされたバージョン番号を比較します。
  • それらが一致しない場合には、ISteamUserStats::ResetAllStats を呼び出し、続いてハードコードされた番号に「バージョン」の統計データを設定します。
    こうすれば、一括消去を実行しなければならない際に、ハードコードされたデータのバージョン番号を変更するだけでよくなります。この一括消去は、ユーザーが新しいビルドを受信した際に実行されます。ただし、一括消去コードを最終ビルドと一緒に配布しないようにだけ注意してください。

    統計データの一貫性

    関連データの整合性が失われた状態を想定することは重要です。たとえば、「GamesWon」、「GamesLost」、そして「GamesPlayed」という 3 つのデータがあるとします。そして、最善を尽くしたにも関わらず、統計データの同期に失敗したとしましょう。その場合、ゲームの勝敗数の合計がプレイされたゲームの総数に合致しなくなってしまいます。これを「Gameslost」の統計データを除去し、代わりに「GamesPlayed」から「GamesWon」を引いて計算した場合、「GamesLost」の数がマイナスになるという不整合が発生することになるかもしれません。この場合、「GamesPlayed」のデータを破棄し、「GamesWon」 + 「GamesLost」で算出するべきでしょう。

    グローバル統計データ

    統計データは管理ページで「総計済み」とマークすることで、そのデータのユーザー全員の総数を保管するよう Steam に指示することができます。これは、エコノミーで総通貨量、しとめた敵の総数、お気に入りの武器、お気に入りのマップ、また実績が良かったチームなどのデータの取得に使用することができます。逆に言えば、「MostKills」のような統計には使用しないでください。複数のユーザーの実績を加算しても意味がありません。統計データがユーザーの手にある場合、このデータは改変されてしまうことがあります。したがって、集計データを利用する際には、最小値、最大値、増加限定(適切な場合)、また最大変更値にしっかりした制限を設定することが不可欠になります。集計データにとって最大変更値は、特別な意味を持ちます。新しい値がアップロードされる際、最大変更値以上にグローバル値が変化することはありません。これにより、チートプレイヤーによる短期間でのグローバル総数への操作を制限することができます。

    グローバル総数にアクセスするには、ISteamUserStats::RequestGlobalStats を呼び出してから、各グローバル統計データ用に ISteamUserStats::GetGlobalStat を呼び出します。さらに、履歴の指定日数に対して、ISteamUserStats::RequestGlobalStats を要求することもできます。この履歴は、毎日のデータの変更量です。その履歴には、ISteamUserStats::GetGlobalStatHistory でアクセスすることができます。

    さらに、クライアントにグローバル実績の達成率をリクエストすることもできます。そうするには、はじめに ISteamUserStats::RequestGlobalAchievementPercentages を呼び出します。次に、ISteamUserStats::GetMostAchievedAchievementInfo、および ISteamUserStats::GetNextMostAchievedAchievementInfo を呼び出して、達成率の高いものから低いものの順に実績をイテレートします。特定の実績の達成率は、ISteamUserStats::GetAchievementAchievedPercent を呼び出すことで取得できます。

    Steam コミュニティ

    ゲームがリリースされると、個々の実績およびグローバル実績の進行状況に関する情報が、Steam コミュニティ内に表示されます。各プレイヤーには、それぞれのコミュニテ プロフィールに、獲得した実績とまだアンロックされていない実績を紹介するページへのリンクが与えられます。
    注意: アプリがコミュニティにある程度認知されるまで、あなたの業績は表示されません。

    それぞれの実績は、Steamworks コントロールパネルで設定されたように、該当するアイコン、名前、説明と共にリストアップされます。実績の名前と説明は、現在選択している言語にローカライズされている場合は、その言語で表示されます。

    またこのページ、そしてゲーム用 Steam メインページの 1 つには、ゲームのグローバル実績統計データセットへのリンクが表示されます。そこには、最も一般的な実績から最も希少な実績までについて、それぞれを獲得しているゲームの Steam プレイヤーの割合が表示されます。これは、プレイヤーが見て楽しめる内容であるのはもちろんのこと、開発者にとっては自分のチャレンジの難易度を確認する素晴らしいリソースになります。(この情報は、Steamstats パートナーサイト上でもご覧いただけます)

    他にも質問がありますか?

    ご質問は、統計データおよび実績に関する掲示板へ投稿してください。