UnityでPhoton(PUN2)を使い、オンライン対戦ボードゲーム(オセロ)を作る

Unityでのオンライン対戦ゲームの作り方を理解すべく、Photon(PUN2)を用いてボードゲーム(オセロ)を作成してみます。
前提として、私はUnity初心者なので、ここであげるやり方は良いものではないかもしれないことをご承知おきください。

まず、PUN2の導入方法や基本的な使用方法等は以下を参考にしています。
URL:https://connect.unity.com/p/pun2deshi-meruonraingemukai-fa-ru-men-sono1

上記の例では、アクション型の対戦ゲームを例にあげています。
本稿では、こちらを参考に簡単なボードゲーム、オセロを作っていこうと思います。

とりあえずオフラインのオセロを作る

まずはオセロを実現するのに必要な構造を設計してみます。
ここではまだ、先にオセロのみに焦点を置く為に、オフラインを想定しています。

ユースケース図?的なもの

■オセロマス
オセロマスには自分が「何行何列目」のマスなのかという情報と、
「マスの状態(何もなし。黒。白の3状態)」及び、ここに「石が置けるかどうか」の情報を持っています。
「石が置けるかどうか」を知る為には、他のマスの情報が必要なのでオセロ盤が情報をセットしてくれます。
また、「マスの状態」に従い、マスの見た目を変えます。

■オセロ盤
オセロマスを64個保持しています。
オセロのルールそのものの処理に記載します。
・石は白と黒順番に置く。
・石は相手の石をとれる場所にしか置けない。
・石が置かれたら挟まれている相手の石をひっくり返す。
・石を置く場所が無い場合は自分の番をスキップする。
・両者共に石が置けなくなったらゲーム終了

■プレイヤー
マウス操作によって石を置くマスを指定する。
参考: PUN2で始めるオンラインゲーム開発入門【その1】
https://qiita.com/JunShimura/items/4547563fbb2691f40626
指定したマスに石を置かせる。

■UI(図に書き忘れた)
オセロ盤の情報を表示する。

以下の①~③を繰り返してゲームを進めます
①マウスクリックされたマスが座標をプレイヤーに返します。
②座標を得たプレイヤーはその座標に石を置くようにオセロ盤に命令をします。
③オセロ盤がルールに基づきゲームを進める。

この設計通りに作ったのがこちら
デバッグ用にマスの数は4×4にしております。

とりあえず最低限の機能が完成。

本来であれば、オフライン向け実装をする前にオンラインを前提とした設計をすべきです。(大きく手戻りする可能性が高い為)
ですが、オフラインからオンラインにする為にはどこを変えなければいけないかをわかりやすくする為に先にオフライン実装を行いました。

オンライン対応化

ここからさらにオンライン対応する為の設計をします。

ここで重要なのは、どのオブジェクトの何のデータを、プレイヤー間で同期更新すればオンライン対戦が実現できるかを考えることです。
大きく分けて2つの案がでてくるかと思います。
①ボード盤の状態を同期する。
 →同期するデータ:盤面の全マスの状態。

②プレイヤーの操作を同期する。
 →同期するデータ:プレイヤーがどこのマスを選んだか。

今回は②案で実装します。
②とした理由については、①案と比べて
・同期すべきデータが少ない(どこのマスを決定したかさえ分かればいい)
・オフライン向けに作成したオセロクラスに手を加えなくてよい。
からです。
デメリットとしては、ゲームスタート時から通しでプレイヤーがいなければなりません。
一度退出して再入出した際に、盤面の再現ができず、続きからできなくなってしまうからです。
まぁ、これに関しては再入出したときのみ②案の同期をすれば良いかとも思いますが、とりあえず今回は①案の同期のみとします。

まずはプレイヤーが2人になります。
プレイヤーが部屋に接続した際に生成されるようにします。

このままでも、2人のプレイヤーが各々の操作で石を置くことができます。
ですが、このままでは今が誰のターンなのかを区別することができません。
なので、プレイヤーの操作を監視し、適切なターンのときのみ石を置く統制役を追加することにします。

※後から気付きましたが、オセロマネージャを用意せずとも RPC(リモートプロシージャコール)を用いたほうが良いです。
参考:https://connect.unity.com/p/pun2deshi-meruonraingemukai-fa-ru-men-sono3

では実装していきます。
まずはプレイヤークラスです。

動作:
マウスクリックしたオブジェクトにアクションを起こさせる関数を実装しています。
これにより、クリックしたマスの座標を取得します。

同期する変数は以下です。
id:各プレイヤーを識別する為のID
data_x:選んだマスの座標
data_z:選んだマスの座標
decision:どこかのマスを選んだことを伝える

上記変数を以下のように同期しています。
参考: PUN2で始めるオンラインゲーム開発入門【その2】
https://connect.unity.com/p/pun2deshi-meruonraingemukai-fa-ru-men-sono2

ここでsendDecision変数を用いてdecision変数を同期していることに注目してください。
decision変数はマスをクリックしたら0→1
クリックしたことによる処理(石を配置)をしたら1→0に戻す
といった使い方をしています。ここで危惧されるのは以下の現象です。

マスをクリックしてdecision変数が0→1になった後、
他プレイヤーの為にdecision変数を同期送信する前に、
処理が完了してdecision変数が1→0に戻ってしまうことです。

こうなってしまうと、石を置いたプレイヤーのゲームアプリ上では相手の手番に進みますが、
他プレイヤーからは相手プレイヤーが石を置いたことが分からず、永遠に手番が進まなくなってしまいます。

この現象を回避する為に、sendDecision変数を使用しています。

また、プレイヤーidを付与する為に
このオブジェクトを生成したオーナーのIDを取得し、格納しています。

次にサーバに接続するためのクラスです。
これは参考サイトのものに、入室した際に各接続者毎にプレイヤーオブジェクトが生成されるようにしただけです。

最後にオセロマネージャクラスです。
各プレイヤーのリクエスト(どこのマスをクリックしたぞという情報)を元に、
そのプレイヤーのターンならば石を置き、違うならリクエストを棄却します。

これにより以下のようなオセロアプリができました。

次回は機能の追加や、見た目のブラッシュアップを行います。

また、オセロクラスとオセロマスクラスのコードを参考に貼っときます。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です