前提条件
Game Chat 2 は、プロジェクトが GDK 用にセットアップされている必要があります。セットアップ方法の詳細については、Microsoft Game Development Kit の使用開始 を参照してください。 Game Chat 2 をコンパイルするには、主要な GameChat2.h ヘッダーをインクルードする必要があります。 適切にリンクするために、プロジェクトは少なくとも 1 つのコンパイル単位に GameChat2Impl.h も含める必要があります (これらのスタブ関数の実装は小さくコンパイラが “インライン” として生成しやすいため、共通のプリコンパイル済みヘッダーをお勧めします)。 Game Chat 2 インターフェースは、C++/CX または従来の C++ のどちらでコンパイルするかをプロジェクトに選択させる必要はありません。どちらでも使用できます。実装では、非致命的なエラー報告の手段として例外をスローすることもありません。例外を使用しないプロジェクトから簡単に利用できます。ただし、実装は致命的なエラー報告の手段として例外をスローします (詳細については、このトピックの後半にある 失敗モデル セクションを参照してください)。初期化
シングルトンの初期化のライフタイムに適用されるパラメーターで Game Chat 2 シングルトンインスタンスを初期化することによって、ライブラリの操作を開始します。シングルトンインスタンスは、次に示すように chat_manager::initialize を呼び出して初期化されます。RegisterAppStateChangeNotification を介してサスペンドおよびレジュームイベントを登録する必要があります。サスペンド時には、chat_manager::cleanup() で Game Chat 2 をクリーンアップする必要があります。レジューム時には、Game Chat 2 を再初期化する必要があります。サスペンド/レジュームサイクルをまたいで使用しようとするとクラッシュする可能性があります。ユーザーの構成
Microsoft Game Development Kit (GDK) タイトルへのユーザーの追加
Game Chat 2 インスタンスにユーザーを追加する前に、そのユーザーが GDK タイトルに追加されていることを確認してください。 これは XUserAddAsync API を使用して行います。この API の使用の詳細については、ユーザー ID と XUser を参照してください。 Game Chat 2 に追加したいユーザーのXUserHandle を取得した後、XUserGetId API を使用してユーザーの XBOX ユーザー ID (XUID) を取得する必要があります。
ユーザーはオンラインである必要があり、このステップにはユーザーの同意が必要です。
XUserGetId は XUID を uint64_t として提供します。Game Chat 2 で使用するために XUID を std::wstring に変換する必要があります。
以下は、XUserHandle を取得した後に Game Chat 2 にユーザーを追加する方法を示すコード例です。
XUserResolveIssueWithUiAsync を呼び出すとシステムダイアログボックスが表示されることに注意してください。
Game Chat 2 へのユーザーの追加
インスタンスが初期化された後、chat_manager::add_local_user を使用して、Game Chat 2 インスタンスにローカルユーザーを追加する必要があります。この例では、ユーザー A がローカルユーザーを表しています。c_communicationRelationshipSendAndReceiveAll は、双方向コミュニケーションを表すために GameChat2.h で定義されている定数です。
chat_user_local::set_communication_relationship を使用して、ユーザー A のユーザー B に対する関係を設定します。
c_communicationRelationshipSendAll は、この単方向コミュニケーションを表すために GameChat2.h で定義されている定数です。
次のように関係を設定します。
chat_manager::remove_user() を呼び出すと、ユーザーオブジェクトが無効になる可能性があります。リアルタイム音声操作 を使用している場合、詳細については チャットユーザーのライフタイム を参照してください。それ以外の場合、chat_manager::remove_user() が呼び出されるとすぐにユーザーオブジェクトが無効になります。ユーザーを削除できるタイミングに関する微妙な制限については、このトピックの後半にある 状態変化の処理 セクションで説明されています。
データフレームの処理
Game Chat 2 は独自のトランスポート層を持ちません。トランスポート層はアプリが提供する必要があります。 このプラグインは、アプリが定期的に頻繁に chat_manager::start_processing_data_frames() および chat_manager::finish_processing_data_frames() の一対のメソッドを呼び出すことで管理されます。これらのメソッドは、Game Chat 2 が送信データをアプリに提供する方法です。 これらのメソッドは高速に動作するように設計されています。専用のネットワーキングスレッドで頻繁にポーリングできます。 これにより、ネットワークタイミングの予測不可能性やマルチスレッドコールバックの複雑さを心配することなく、キューに入っているすべてのデータを取得できる便利な場所が提供されます。chat_manager::start_processing_data_frames() が呼び出されると、キューに入っているすべてのデータが game_chat_data_frame 構造体ポインターの配列で報告されます。
アプリは配列を反復処理し、ターゲットエンドポイントを検査し、アプリのネットワーキング層を使用して適切なリモートアプリインスタンスにデータを配信する必要があります。
配列内のすべての game_chat_data_frame 構造体の処理が完了した後、配列は chat_manager:finish_processing_data_frames() を呼び出してリソースを解放するために Game Chat 2 に戻す必要があります。
これは次の例に示されています。
状態変化の処理
Game Chat 2 は、受信したテキストメッセージなどの更新をアプリに提供します。これは、アプリが定期的に頻繁に chat_manager::start_processing_state_changes() および chat_manager::finish_processing_state_changes() の一対のメソッドを呼び出すことで行われます。 これらのメソッドは高速に動作するため、UI レンダリングループの各グラフィックスフレームで呼び出すことができます。 これにより、ネットワークタイミングの予測不可能性やマルチスレッドコールバックの複雑さを心配することなく、キューに入っているすべての変化を取得できる便利な場所が提供されます。chat_manager::start_processing_state_changes() が呼び出されると、キューに入っているすべての更新が game_chat_state_change 構造体ポインターの配列で報告されます。
アプリは配列を反復処理し、より具体的な型を確認するために基本構造体を検査し、基本構造体を対応するより詳細な型にキャストし、その更新を適切に処理する必要があります。
配列内の現在利用可能なすべての game_chat_state_change オブジェクトの処理が完了した後、配列は chat_manager::finish_processing_state_changes() を呼び出してリソースを解放するために Game Chat 2 に戻す必要があります。
これは次の例に示されています。
chat_manager::remove_user() はユーザーオブジェクトに関連付けられたメモリを直ちに無効にし、状態変化にはユーザーオブジェクトへのポインターが含まれる可能性があるため、状態変化を処理中に chat_manager::remove_user() を呼び出してはなりません。
テキストチャット
テキストチャットを送信するには、chat_user::chat_user_local::send_chat_text() を使用します。 これは次の例に示されています。アクセシビリティ
アクセシビリティには、テキストチャットの入力と表示のサポートが必要です。 テキスト入力が必要なのは、物理キーボードが広く使用されていないプラットフォームやゲームジャンルでも、ユーザーがテキスト読み上げ支援技術を使用するようにシステムを構成できるためです。 同様に、テキスト表示が必要なのは、ユーザーが音声認識技術を使用するようにシステムを構成できるためです。 これらの設定は、ローカルユーザーに対してそれぞれ chat_user::chat_user_local::text_to_speech_conversion_preference_enabled() および chat_user::chat_user_local::speech_to_text_conversion_preference_enabled() メソッドを呼び出して検出できます。ユーザー設定に基づいて条件付きでテキストを有効にすることをお勧めします。テキスト読み上げ
ユーザーがテキスト読み上げを有効にしている場合、chat_user::chat_user_local::text_to_speech_conversion_preference_enabled() はtrue を返します。この状態が検出された場合、アプリはテキスト入力の方法を提供する必要があります。
実際または仮想のキーボードから提供されたテキスト入力を取得した後、文字列を chat_user::chat_user_local::synthesize_text_to_speech() メソッドに渡します。Game Chat 2 は、文字列とユーザーのアクセシビリティ音声設定に基づいて音声データを検出および合成します。
これは次の例に示されています。
chat_user::chat_user_local::synthesize_text_to_speech() がテキスト読み上げを有効にしていないユーザーで呼び出された場合、Game Chat 2 は何のアクションも実行しません。
音声認識
ユーザーが音声認識を有効にしている場合、chat_user::chat_user_local::speech_to_text_conversion_preference_enabled() はtrue を返します。この状態が検出された場合、アプリは文字起こしされたチャットメッセージに関連付けられた UI を提供する準備をする必要があります。Game Chat 2 は各リモートユーザーの音声を自動的に文字起こしし、game_chat_transcribed_chat_received_state_change 構造体を介して公開します。
音声認識のパフォーマンスに関する考慮事項
音声認識が有効になっている場合、各リモートデバイス上の Game Chat 2 インスタンスは、スピーチサービスエンドポイントとの WebSocket 接続を開始します。 各リモート Game Chat 2 クライアントは、この WebSocket を介してスピーチサービスエンドポイントに音声をアップロードします。スピーチサービスエンドポイントは、時々リモートデバイスに文字起こしメッセージを返します。 リモートデバイスは、その後、文字起こしメッセージ (つまり、テキストメッセージ) をローカルデバイスに送信します。文字起こしされたメッセージは、レンダリングのために Game Chat 2 によってアプリに提供されます。 したがって、音声認識の主なパフォーマンスコストはネットワーク使用量です。 ネットワークトラフィックのほとんどは、エンコードされた音声のアップロードです。 WebSocket は、“通常の” 音声チャットパスで Game Chat 2 によって既にエンコードされている音声をアップロードします。アプリは chat_manager::set_audio_encoding_bitrate を介してビットレートを制御できます。UI
ユーザーに UI が表示される場所、特にスコアボードなどのゲーマータグのリストでは、ユーザーへのフィードバックとしてミュート/発話中のアイコンも表示することをお勧めします。 これは、chat_user::chat_indicator() を呼び出して、そのユーザーの現在の瞬間的なチャット状態を表す game_chat_user_chat_indicator 列挙を取得することによって行います。次の例は、chatUserA 変数が指す chat_user オブジェクトのインジケーター値を取得して、iconToShow 変数に割り当てる特定のアイコン定数値を判定する方法を示しています。
ミュート
chat_user::chat_user_local::set_microphone_muted() メソッドは、ローカルユーザーのマイクのミュート状態を切り替えるために使用できます。マイクがミュートされている場合、そのマイクからの音声はキャプチャされません。ユーザーが Kinect などの共有デバイスを使用している場合、ミュート状態はすべてのユーザーに適用されます。 chat_user::chat_user_local::microphone_muted() メソッドは、ローカルユーザーのマイクのミュート状態を取得するために使用できます。このメソッドは、chat_user::chat_user_local::set_microphone_muted() の呼び出しを介してソフトウェアでローカルユーザーのマイクがミュートされているかどうかのみを反映します。このメソッドは、たとえば、ユーザーのヘッドセットのボタンによって制御されるハードウェアミュートは反映しません。
Game Chat 2 を介してユーザーのオーディオデバイスのハードウェアミュート状態を取得する方法はありません。
chat_user::chat_user_local::set_remote_user_muted() メソッドは、特定のローカルユーザーに関するリモートユーザーのミュート状態を切り替えるために使用できます。リモートユーザーがミュートされている場合、ローカルユーザーはそのリモートユーザーからの音声を聞いたり、テキストメッセージを受信したりしません。
悪い評判の自動ミュート
通常、リモートユーザーはミュートされていない状態で開始します。 Game Chat 2 は、次の場合にユーザーをミュート状態で開始します。- リモートユーザーがローカルユーザーの友達ではない場合。
- リモートユーザーに悪い評判フラグが付いている場合。
chat_user::chat_indicator() は game_chat_user_chat_indicator::reputation_restricted を返します。
この状態は、リモートユーザーをターゲットユーザーとして含む chat_user::chat_user_local::set_remote_user_muted() の最初の呼び出しによって上書きされます。
権限とプライバシー
ゲームによって構成されたコミュニケーション関係に加えて、Game Chat 2 は権限およびプライバシー制限を強制します。 Game Chat 2 は、ユーザーが最初に追加されたときに権限とプライバシー制限のルックアップを実行します。これらの操作が完了するまで、ユーザーのchat_user::chat_indicator() は常に game_chat_user_chat_indicator::silent を返します。
ユーザーとのコミュニケーションが権限またはプライバシー制限の影響を受ける場合、ユーザーの chat_user::chat_indicator() は game_chat_user_chat_indicator::platform_restricted を返します。
プラットフォームのコミュニケーション制限は、音声チャットとテキストチャットの両方に適用されます。テキストチャットがプラットフォーム制限によってブロックされているが音声チャットはブロックされていない、またはその逆というインスタンスは決して発生しません。
chat_user::chat_user_local::get_effective_communication_relationship() は、権限およびプライバシー操作が不完全であるためにユーザーがコミュニケーションできないタイミングを識別するのに役立ちます。
これは、Game Chat 2 によって強制されるコミュニケーション関係を game_chat_communication_relationship_flags の形式で返し、関係が game_chat_communication_relationship_adjuster 列挙の形式で構成された関係と等しくない可能性がある理由を返します。
たとえば、ルックアップ操作がまだ進行中の場合、game_chat_communication_relationship_adjuster は game_chat_communication_relationship_adjuster::initializing になります。
このメソッドは UI に影響を与えるために使用すべきではありません (詳細については、このトピックの前半にある UI セクションを参照してください)。
Game Chat 2 が権限の問題に遭遇した場合、communication_relationship_adjuster_changed 状態変化で報告されます。
Game Chat 2 が回復不可能な理由でユーザーの権限を取得できなかった場合、game_chat_communication_relationship_adjuster::privilege_check_failure アジャスターとして報告されます。
Game Chat 2 がユーザーが解決できる可能性のある理由でユーザーの権限を取得できなかった場合、game_chat_communication_relationship_adjuster::resolve_user_issue アジャスターとして報告されます。
ユーザーに UI で解決可能かもしれない権限が欠落している場合、game_chat_communication_relationship_adjuster::privilege アジャスターとして報告されます。
これらの場合、コミュニケーションは制限されます。
以下は、ユーザーが次の一般的な問題のいずれかを抱えているかどうかを確認する方法の例です。
- Game Chat 2 が権限をチェックするために、ユーザーが XBOX services に同意する必要があります。
- ユーザーのアカウントが権限を拒否するように構成されている (たとえば、子供アカウントで、チャットを使用できない)。
game_chat_communication_relationship_adjuster::privilege アジャスターで報告される問題については、XUserPrivilegeOptions::None および XUserPrivilege::Communications を指定して XUserResolvePrivilegeWithUiAsync を呼び出し、問題の解決を試みることができます。
game_chat_communication_relationship_adjuster::resolve_user_issue アジャスターで報告される問題については、URL に nullptr を指定して XUserResolveIssueWithUiAsync を呼び出し、問題の解決を試みることができます。
権限の問題があることを示す UI を表示することをお勧めします。ユーザーがボタンを押すかメニューオプションで問題の解決を試みるかどうかを決定できるようにします。
ユーザーは、問題を解決できない、または解決したくない場合があります。
ユーザーが問題を解決した場合、その効果はユーザーが次回 Game Chat 2 に追加されるときに発揮されます。
chat_manager::remove_user() は状態変化を処理中に呼び出してはなりません (つまり、chat_manager::start_processing_state_changes() が呼び出された後、対応する chat_manager::finish_processing_state_changes() の呼び出しの前)。状態変化の処理中に
chat_manager::remove_user() を呼び出すと、削除されたユーザーに関連付けられたメモリが無効になる可能性があります。
game_chat_communication_relationship_adjuster::privilege アジャスターが見られ、ユーザーの権限の解決を試みたい場合、状態変化の処理が終わるまで待ってから試みる必要があります。XUserResolvePrivilegeWithUiAsync を呼び出すために必要な XUID から XUserHandle を取得するには、XUserFindUserById API を使用して新しい XUserHandle を取得できます。または、XUserAddAsync で取得したものを保持し、どの XUID がそれにマップされているかを追跡することもできます。
以下は、これらの問題を解決する方法の例です。
クリーンアップ
アプリが Game Chat 2 を介したコミュニケーションを不要になったとき、chat_manager::cleanup() を呼び出す必要があります。 これにより、Game Chat 2 はコミュニケーションを管理するために割り当てられたリソースを回収できます。失敗モデル
Game Chat 2 の実装は、非致命的なエラー報告の手段として例外をスローしません。例外を使用しないプロジェクトから簡単に利用できます。 ただし、Game Chat 2 は致命的なエラーを通知するために例外をスローします。 これらのエラーは、インスタンスを初期化する前に Game Chat インスタンスにユーザーを追加したり、Game Chat 2 インスタンスから削除された後にユーザーオブジェクトにアクセスしたりするなど、API の誤用の結果です。 これらのエラーは開発の初期段階で捕捉されることが期待され、Game Chat 2 との対話に使用されるパターンを変更することで修正できます。 このようなエラーが発生した場合、例外が発生する前に、エラーの原因に関するヒントがデバッガーに出力されます。一般的なシナリオの構成方法
プッシュ・トゥ・トーク
プッシュ・トゥ・トークは、chat_user::chat_user_local::set_microphone_muted() で実装する必要があります。 発話を許可するにはset_microphone_muted(false) を、制限するには set_microphone_muted(true) を呼び出します。
このメソッドは、Game Chat 2 から最も低いレイテンシの応答を提供します。
