XGameSave のベスト プラクティス
このトピックでは、XGameSave
API の使用方法に関するベスト プラクティスをいくつか紹介します。
ストレージ領域を取得するタイミング
一般に、ゲームは、ユーザーがログインしてゲームをプレイする意思を示した後に、XGameSave
のストレージ領域の取得を試行する必要があります。 ゲームは、XGameSaveInitializeProvider または XGameSaveInitializeProviderAsync を呼び出すことで、ストレージ領域を取得します。
ユーザーの接続ストレージ領域を取得するための実行時間は変動する可能性があります。 ゲームでは、ユーザーがサインアウトを開始したことに対する応答、またはシステムから一時停止通知を受け取ったことに対する応答としてではなく、メインの実行中にこの処理を行う必要があります。 Connected Storage 領域の取得を、長い一連のデータ読み込みに合わせることで、並列に処理できるようにすることも検討してください。
ゲームから XGameSave
ストレージ領域へのアクセスを要求されると、システムは同期プロセスを実行し、Xbox One コンソール間でユーザーのセーブ データが一貫した状態で維持されるようにして、そのデータをオフライン プレイで使用できるようにします。 同期は、その所要時間が変動する可能性があり、ユーザーの判断を必要とする場合があるため、そのプロセスのさまざまな段階でシステムからユーザーに UI が表示されることがあります。
同期 UI がアクティブな場合でも、ユーザーは Xbox ボタンを押していつでもアプリを離れることができます。 システムは UI を非表示にし、ユーザーの操作なしで可能な範囲で同期は続行されます。 ユーザーがアプリケーションに戻ると、同期が完了していない限り、UI が再度表示されます。 UI が非表示のときに、ユーザーの選択をシステムが勝手に推測することはありません。
ストレージ領域の有効期間
一般に、一度ゲームの特定のストレージ領域に XGameSaveProviderHandle
が指定されると、そのゲーム セッションの有効期間にわたってそのハンドルが保持されます。 ハンドルが保持されてもゲームのパフォーマンスに悪影響を及ぼすことはありません。 一度解放されたハンドルを再取得しようとすると、時間がかかる場合があります。
オンデマンド同期を使用するタイミング
ほとんどのゲームでは、オンデマンド同期を使用してはなりません。 ゲームは、ストレージ領域を取得するときに、XGameSaveInitializeProvider または XGameSaveInitializeProviderAsync のいずれかの syncOnDemand
パラメーターに true
を渡すことで、オンデマンド同期を使用するよう選択できます。
オンデマンド同期は、ゲームがセーブ データを同期するときに変更されます。
- オンデマンド同期を使用しないときは、ストレージ領域が取得されるときにすべての同期が発生します。 セーブ データのサイズなどの条件によっては、ゲームの上に UI が表示されることがあります。
- オンデマンド同期を使用すると、同期はゲームが XGameSaveReadBlobData または XGameSaveReadBlobDataAsync のいずれかを呼び出して、ストレージ コンテナーからデータの読み取りを試行するときにのみ発生します。 同期が必要な場合は、これによりユーザーに UI が表示されることがあります。
オンデマンド同期は、次のすべての条件が満たされている場合にのみ使用してください。
- ゲームに多数のコンテナーがあり、それぞれのサイズが大きい。
- ゲームが初めてストレージ コンテナーから読み取る必要があるときに、アクティブなゲーム プレイの最中でないこと。最初の読み取りでは、コンテナー全体の同期が求められる場合があります。
- ゲーム セッションが限られた数のコンテナーにのみアクセスする必要がある。
誤った上書きからの保護
保存されたゲームの同期に時間がかかる。 ユーザーがセーブ データの同期を取り消すことを選択する場合があります。 これを行うときに、ストレージ領域とそのコンテナーがローカル デバイス上になかったり、一部のみ同期されたりする場合があります。 ゲームは何がダウンロードされている可能性があるかについて誤った想定をしないように、ゲーム自体を保護する必要があります。
既にデバイス上にある作成済みのコンテナーで XGameSaveCreateContainer を呼び出すと、コンテナーが開かれ、ゲームがそのコンテナーを更新することを許可します。
XGameSaveCreateContainer を呼び出し、そのコンテナーがデバイス上に存在しない場合 (まだ同期されていないか、ゲームが意図的に新しいコンテナーを作成している場合) は、新しいコンテナーが作成されます。 何か新しいことを実行する意図があったのであれば、これは期待通りの動作です。 何かが同期されなかったためこれが発生した場合は、新しく (意図せず) 作成されたコンテナーがクラウド上のコンテナーと競合すると、データが失われる可能性があります。
このシナリオから保護するには、create
を呼び出す前に、必ず目的のコンテナーを列挙してください。 ゲームは、XGameSaveEnumerateContainerInfo または XGameSaveEnumerateContainerInfoByName のいずれかを呼び出すことで、コンテナーを列挙できます。
セーブするタイミング
ゲームで一時停止通知を受け取るたびに、ゲームでは少なくとも、関連データをセーブして、システムがコンテキストに応じてユーザーの適切な状態に戻れるようにする必要があります。
定期的な、自動的な、またはユーザーが開始するセーブをゲームの設計で使用している場合、一時停止通知を受け取ったとき以外にも XGameSave
を呼び出すことができます。 そうすることで、停電やクラッシュでデータを失うリスクを減らすことができます。
ユーザーがサインアウトすると、そのユーザーの XUser
オブジェクトは、ゲームがサインアウト延期を実行したと想定して有効なままになります。 この遅延により、ゲームは XGameSave
API を使用して最終的な保存操作を実行する場合があります。
一般的なガイダンス
依存関係のあるデータをコンテナーをまたいで格納しない
依存関係のあるデータを複数のコンテナーをまたいで格納しないでください。 不完全な同期、停電、またはその他のエラー状況によって、コンテナーが分離される場合があります。 1 つのコンテナーに格納されるデータは、そのコンテナー内で自足し、一貫している必要があります。
ユーザーが本体の電源を切ったり、アプリを離れたりすることを妨げない
タイトルで、セーブ時にユーザーが本体の電源を切ったり、アプリから離れたりすることを妨げないようにしてください。 Xbox One では、タイトルは一時停止イベントを受信し、XGameSave
API を使用して状態をセーブする時間が 1 秒あります。 システムが完全にシャットダウンするか低電力状態になる前に、データがハード ドライブに適切にコミットされることがシステムで保証されています。
ユーザーが別のタイトルをプレイするためにタイトルのディスクを取り出した場合も、同じ一時停止プロセスが実行されます。
XGameSave
API の非同期バージョンを使用することをお勧めします。 これにより、システムがセーブ データを書き出している間、タイトルは中断コードの残りを続行できます。 使用例については、XGameSaveSubmitUpdateAsync を参照してください。
ゲームがデータを読み込もうとしているときにユーザーに通知する
ゲームが XGameSaveInitializeProvider 呼び出しの完了を待機しているときに、アプリがデータを読み込もうとしていることをユーザーに視覚的に示してください。 アプリが全画面表示で実行されているとき、システムは同期プロセス中に UI を表示しますが、ユーザーがホーム画面に移動すると、この UI は非表示になります。 この状況が発生する可能性が高いのは、システムが、要求された XGameSave
記憶領域の大量のデータを同期している場合です。
XGameSave ストレージ領域を保持する
XGameSaveProviderHandle
オブジェクトを、読み取りまたは書き込みイベントが発生するたびに取得するのではなく、保持するようにします。 ハンドルを長期間保持することによってパフォーマンスや堅牢性に悪影響を及ぼすことはありません。
注意
任意の時点でいずれかの XGameSave
API が E_GS_HANDLE_EXPIRED
を返す場合、ゲームはすべての XGameSave
オブジェクトを破棄し、XGameSaveProviderHandle
を再取得する必要があります。
データ サイズを小さくする
セーブ データのサイズを小さくします。 本体がオンラインのときに、ストレージ領域内のすべてのユーザー データがクラウドにアップロードされます。 データ形式を最適化して、遅延と帯域幅の使用量が最小限に抑えられるようにしてください。
保存データの物理的なサイズを超えても、コンテナー内の BLOB の数を考慮してください。 コンテナーが 1 MB であっても、そのコンテナーに 1000 個の BLOB (それぞれ 1 KB) がある場合は、よりサイズの大きな BLOB が少数あるコンテナーよりも同期に時間がかかります。
ユーザーがセーブを必要としていないことを確認する
XGameSaveInitializeProvider や XGameSaveSubmitUpdate から E_GS_OUT_OF_LOCAL_STORAGE
エラーが返されていないかどうかをチェックします。 ユーザーに質問して、本当にセーブせずにプレイするかどうかを確認します。 ユーザーがゲームをセーブすることを希望する場合は、操作を再試行します。
ユーザーのクォータをチェックし、領域をクリアするよう要求する
XGameSaveSubmitUpdate によって E_GS_QUOTA_EXCEEDED
エラーが返されていないかチェックします。
ゲームでこのメッセージを受け取った場合は、領域をいくらか空けるまで新しいデータをセーブできないことをユーザーに通知します。 そのための UI を表示します。 各ユーザーには、ゲームごとに 256 MB のデータが与えられます。
後で復元できるようにメニューの状態を保存する
コアのゲーム データに加えて、メニューの状態やその他のゲームの設定を保存します。 ユーザーが別のゲームをプレイしてから元のゲームに戻ってきた場合、コンテキストに応じて適切なメニュー状態を復元します。
サインインしているユーザーの変化に対応する
ゲームが一時停止されている間にユーザーがサインアウトする可能性があります。 ゲームが再開されるとき、サインインしていた一連のユーザーが変わっていないかどうかを確認する必要があります。 変わっているときは、メニューなどのゲーム内の適切な場所に案内することを検討してください。
PC でセーブデータがセキュリティで保護されない
PC 上のセーブデータは保護もセキュリティ保護もされません。 ゲーマーは、このようなセーブデータを見つけて改ざんすることができます。 ゲームでは、デバイスにローカルに保存されているセーブデータ内の重要なデータに依存しないようにしてください。 高度な保護を必要とするゲームでは、書き込んだデータに対して独自のハッシュ ソリューションを実装し、後でそのデータを読み取るときにそのハッシュを検証できます。