Memory Game デモ

Memoryデモは非同期的にプレイできるシンプルな2プレイヤーゲームの作業用サンプルです。
マッチメイキング、「保存されたゲーム」、ターンの順番、対戦相手がインアクティブな場合のプッシュ通知などの機能がありますので、以下で説明します。

Memory メインメニュー

クライアントは Unity SDKを使用します。

サーバーサイドには、参考用に非同期ゲームが実装されています。
これはダッシュボードで有効化できます。 ソースはGitHubから入手できます。

クライアントの準備

MemoryDemoSceneを読み込み、EditorにAppIDを入力すれば、クライアントを実行するための準備は完了します。

無料サインアップ後に、RealtimeダッシュボードからアプリケーションのAppIDを取得してください。

ダッシュボードからAppIDをコピーして、MemoryDemoSceneを開いてください。
「スクリプト」GameObjectとMemoryGuiコンポーネントで、「AppID」を設定してください。

MemoryGuiコンポーネント

サーバーの準備

Realtimeのダッシュボードから、「管理」をクリックしてアプリケーションの管理ページへ進んでください。

Realtimeダッシュボードに表示された「MemoryDemo」サンプルアプリケーション

最下部のWebhookセクションにある「新しいWebhookの作成」ボタンで、新しいWebhook設定を作成します。

Webhookが全く設定されていないWebhookセクション

ドロップダウンリストから、「WebHooks 1.2デモ」を選択します。
独自のウェブサービスが準備できている場合には、「WebHooks 1.2」を選択することもできます。
このデモでは、関連するパラメータのみを以下のスクリーンショットで表示しています。

スクリーンショットに表示されるBaseUrlはデフォルトなので、独自のカスタムURLに変更してください。

Webhookの詳細については、こちらのページを参照してください。

Memoryデモ用のWebhook設定例

コードの参照

Memoryデモを最大限活用するにはコードを参照してください。
Unity Inspector の設定はビジュアルやオプションを定義しますが、ロジックはコードで処理されます。

このデモで確認すべきクラスはMemoryGuiMemoryBoardMemoryGameClient、およびNamePickerGuiです。

認証

ターンベースゲームでは、ユーザーが重要な役割を担います:
ユーザ毎にゲームリストを残す必要があります。そのリストにはuserIDでアクセスするのが理想的です。
簡潔にするため、このデモではパスワードを必要としません。何を入力してもユーザーIDとして許容します。

実際にユーザーアカウントの認証をおこなうには、Photonのカスタム認証機能を使用できます。 詳細は ドキュメントのカスタム認証ページを参照してください。

参照用に、パッケージには2番目のシーン「CustomAuthDemo」が含まれています。
このシーンでは、クライアントサイドに認証を実装する方法を説明します。

マッチメイキング

このデモは、簡単なマッチメイキングのワークフローを使用しています:
ルームへの参加をランダムに試行し、失敗した場合には新たなルームを作成します。

詳細情報はドキュメントのマッチメイキングとロビーページを参照してください。

マッチメイキングはルームに少なくとも1人のプレイヤーが参加していないと機能しません。
プレイヤー1人ではできることが限られているため、プレイヤーが1人の場合にはルームのマッチメイキングにかかる時間は短くなります。

マッチメイキングをおこなうには、まずguiエレメントがNewGameMsg()を呼び、続いてOpJoinRandomRoom()が呼ばれます。
他のオペレーションへのレスポンスと同様に、このコールへのレスポンスがOnOperationResponseを呼びます。
必要に応じて、MemoryGameClientMemoryGameClient.CreateTurnbasedRoom()で実際のルーム作成コードを呼びます。

ステートの保存

明示的に放棄されたゲームでない限り、後から継続することができます
これはゲームの最中にクライアントがクローズされた場合や、切断された場合を含みます。

Photon Realtimeはバッファされたイベント、およびルームとプレイヤーのすべてのプロパティを自動的に保存します。
プレイヤーがルームに再び参加すると、アクティブおよびインアクティブなプレイヤーのプロパティとバッファされたイベントを取得します。
このデータを使ってプレイヤーはステートの再現をおこない、プレイを続行できます。

Memoryゲームでは、ボード上のタイルの履歴を保持する必要があります。

Memory Board

Memory Board

キャッシュされたイベント

ルーム内のアクティブなプレイヤーのみにイベントを送るだけでなく、参加または「復帰」するプレイヤー向けに意図的にイベントをキャッシュすることもできます。
ルームは到着した順にイベントをキャッシュし続け、参加するプレイヤーが「ライブ」イベントを取得する前に、キャッシュしたイベントを送信します。

Photon Realtimeではキャッシュされたイベントも保存され、プレイヤーが後にゲームを続行するたびに送信されます。
このデモでは、キャッシュされたイベントは使用しませんが、以下にOpRaiseEventコールの例を示します:

C#

public void CachedRaiseEvent(byte evCode, object content)
{
    // the content can be anything Photon-serializable. Most often a Hashtable is used.
    RaiseEventOptions options = new RaiseEventOptions() { CachingOption = EventCaching.AddToRoomCache };
    this.OpRaiseEvent(evCode, content, true, options);  // cached events should be sent reliable
}  

通常どおり、ターンベースゲームで保存されたイベントはOnEvent() を呼んでコードにパスされます。

ターンの履歴を長く残す必要がない場合(再生用)、使用されていないイベントのキャッシュをクリアしてゲームの読み込みを加速する必要があります。 少し分かりにくいのですが、これはOpRaiseEventでおこないます。この場合、CachingOptionをEventCaching.RemoveFromRoomCacheに設定する点に留意してください。

プロパティ

Memoryゲームはゲーム全体のステートをルームプロパティのセットとして保存します。
頻繁に変化しない値で、最新の値のみを保存する必要がある場合にはプロパティが最適です。

もっとも最適な方法は、ルームプロパティの一部を選択し「保存されたゲーム」リストで利用可能にすることです。

Photon Realtimeでは、すべてのプレイヤーがインアクティブになるとすべてのプロパティが保存されます。
このため ダッシュボードで「IsPersistent」を「true」に設定する必要があります。

デモでは、個々のタイルのプロパティ内でタイルIDをストリングキーとし、各タイルを保存します。
このようにして、各タイルの個々のアップデートが可能になります。 ただし、デモでは各ターンの終了時に常にゲームステート全体を保存します。

Memoryゲームの主要な点は、他のプレイヤーが裏返したタイルが見えるということです。
少なくともタイルが一致しなかった場合です。

この機能を実現するには、プレイヤーは完了後にターンを受け渡しません。
その代わりに裏返したタイルは両方とも保存され、ロジックによって他のタイルを選択できなくなります。
対戦相手は準備が出来次第、タイルを見せてターンを「引き継ぐ」必要があります。

スコアやターンカウンターも、保存されるプロパティの一部です。

MemoryGameClient.csSaveBoardToPropertiesLoadBoardFromPropertiesを確認してください。

保存されたゲーム

Photon Realtimeは各ルームのステートを保存するだけでなく、各ユーザーのゲームリストも保存します。
ユーザーが決まったアカウントでログインした場合(すなわち、同じUserIdでログインした場合)、ユーザーが別のデバイスに切替えた場合でもこのリストを利用できます。

保存されたゲームの取得

クライアントは、保存されたゲームのリストにWebRPCコールでアクセスします。
WebRPCは、固有のウェブサービスで実行される単純なオペレーションです。

WebRPCはクライアントサイドから簡単に呼ぶことができます:

C#

Dictionary<string, object>() jsonParameters = new Dictionary<string, object>();
this.GameClientInstance.OpWebRpc("GetGameList", jsonParameters);

PhotonはWebhook用に設定されたBaseUrlを使用し、最後に「GetGameList」を追加します。
もちろん「Base Path」として設定されたサーバーは、このパスの下にプレイヤーごとのゲームリストを提供する必要があります。

この場合Dictionary jsonParametersは不要ですが、必要な場合にはこのDictionaryでWebサーバーにパラメータを渡す方法を参照できます。
Photonは、Webサービスにユーザーに関する情報(UserIDなど)を自動的に提供します。

保存されたゲームの返されたリストには、プレイヤーが再参加できるルームの名前が含まれています。
サーバーは、ユーザーがそのルームで使用していたactorNumberもルームごとに送信します。
最後に、ロビーで利用可能なルームプロパティのリストを提供している場合には、デフォルトの実装でそれらのルームプロパティもGetGameListに送信されます。

MemoryGameClientはそれらのプロパティをList<SaveGameInfo> SavedGamesに変換し、ルームリストの表示に使用します。
デモでは、ゲームごとにターンの順番や対戦相手を示すうえで適切な量のデータを送信します。 ここでは、実際のルーム名は重要ではありません。

注:送信するデータを最小限にして、プレイヤーへの負荷を減らしてください。

GetGameList WebRPCの詳細な説明は、こちらを参照してください。

保存したゲームを開く

プレイヤーはゲームに「再参加する」ことで保存されたゲームに戻ることができます。
ルームに戻るには、ルームの名前を知っている必要があります。

この処理は、MemoryGui.LoadGameMsg()で実行されます。

C#

this.GameClientInstance.OpRejoinRoom(roomName);

拡張について

このデモにはまだ未完全な部分があります。 特に、以下の部分について調整が必要かもしれません・・・

  • プッシュ通知。
  • このゲームは、Webhookが構成されていないことを検知できません。
    通知を表示するよう設定は可能です。
  • 切断された場合、その通知が表示されません。
  • 他のプレイヤーがアクティブかどうか表示する必要があります。現状では、待機すべきかどうかプレイヤーは判断できないためです。
  • オンライン中のプレイヤーの人数の表示。
  • ...

さあ、プレイしてみましょう!

Back to top