Unity1Weekでリアルタイムオセロを制作したという話
初めに
UnityRoomというUnityのゲームがアップロードできるサイトで、
1週間でゲームを作る「Unity1週間ゲームジャム」というのが開催されていたので参加しました。
私は「リアルタイムオセロ」というゲームを制作しました。
下記URLからプレイ可能です!
制作に大体45日くらいかかっています (1週間で作れてないジャン......)。
なぜオセロがベースのゲームを作ったか
自身が参加しているUnityのコミュニティでオセロ制作RTAが話題になり、
自分も作ったから。というのが理由の1つになります。
実際、「のーまるもーど」はそこで作成した普通のオセロが入ってます。
ただ、何か一歩違ったモードも用意したいと思い考えたのが
リアルタイムによるオセロバトルです。
(「りあるたいむばとるもーど」でプレイできます)
将棋のゲームには リアルタイム将棋 というものあるので、
オセロでも面白いのでは?と思い作成しました。
2人が同じ位置に駒を置けちゃう問題
まず最初に自分を苦しめたのが、
同じ場所に2人とも駒を置いたことになる現象でした。
両者がほぼ同時に駒を置く
↓
両者とも置いた位置に駒は置かれていないので、自身の駒を置く
↓
両者が駒を置けたので相手に駒を置いたことを知らせる
↓
_人人人人人人_
> 置いてある <
 ̄Y^Y^Y^Y^Y ̄
原因は両者が自身のデータを正としていることです。
時間によって状況が変わるような通信ゲームではマスタークライアントの
データを正として置いたかどうかを判断するのが良いと思います。
Aさん(マスタークライアント), Bさんがほぼ同時に駒を置く
↓
Aさんの駒の状態を判断し置かれている駒がないのでAさんの駒を置く
↓
Aさんは他のユーザーに駒の置きを通達する
↓
Bさんの置き予約情報が来たのでAさんは駒の状態をチェックする
↓
Aさんのほうは駒が置かれているので何もしない
↓
Bさんは駒が置かれた情報を受けて自身の駒情報を更新する
アイテムが1つしかないのに2人とも取得できたといったような
現象が発生しないようにするのにも上の方法が使えます。
マスタークライアント(上でいうとAさん)の送った情報が受け取り側で
順番が変わってしまうこともあり得るので、
もしも順番がわかってしまうと破綻する場合は、
何番目にするべき処理なのかを一緒に送るとよいです。
盤面情報が一致しなくなる問題
上で2人が同じところに駒を置いてしまうような問題は解決したものの、
ほぼ同時に置くと置いた後の結果が変わることがある
ということが判明しました。
原因は置けたという情報がプレイヤーに送られるタイミングによって
処理順が変わることが問題でした。
当初、置いてから反映までの処理は
置きたいという情報を受け取る
↓
置けるかどうかをマスタークライアントが判断する
okならマスタークライアントは駒を置いておくが、
ひっくり返せる駒は置いた情報を受け取ってからにする
↓
全プレイヤーに置けたことを伝える
↓
置けた情報を受けたとったユーザー(マスタークライアントも含む)は
置けた位置に駒を置き、ひっくり返される駒を調べてひっくり返す。
(クライアントマスターはここでひっくり返す)
となっていました。
ログを仕込みまくって確認したところ、バグ発生時には
置きたいという情報を受け取る
↓
置けるかどうかをマスタークライアントが判断する。
okなら置きたいといってたとこに駒を置く (1回目)
↓
全プレイヤーに置けたことを伝える
↓
置きたいという情報を受け取る
↓
置けるかどうかをマスタークライアントが判断する。
okなら置きたいと言ってたとこに駒を置く。(2回目)
↓
全プレイヤーに置けたことを伝える
↓
置けた情報を受けたとったユーザー(マスタークライアントも含む)は
置けた位置に駒を置き、ひっくり返される駒を調べてひっくり返す。
(1回目の置いた情報がここで受け取られる)
となっていました。
1回目と2回目の間にひっくり返し忘れているのがわかりますでしょうか?
そうなると、ひっくり返った結果置けるはずの箇所に置けなくなり
さらにマスタークライアントから受け取った置けた位置をもとに
マスタークライアントでないユーザーはひっくり返すため、
最終的な結果が変わってしまっていまいます。
・ほぼ同時に置かないと発生しない
・置き方によっては結果は変わらない
ということもあり再現や修正が非常に難しかったです。
結局、マスタークライアントは駒を置きたいという情報を受け取った際、
置けた場合に置いたことによる他の駒をひっくり返す処理も
全プレイヤーに伝える前に行ってしまうことで回避しました。
ネットワーク対戦ゲームでのデバッグ
Photonではブレイクポイントを用いたデバッグが困難なため、
Debug.Log()を開発段階で仕込んでおくことをお勧めします。
また、Unityで通信対戦のデバッグする際はビルドして
確認することになりますが、
ビルドした側のログは確認できるようにするのが面倒なので
SRDebugger のようなものを使うととても便利です。
簡単にログ出力できて楽です。
ただ、本番用ビルド時にログ表示できるようにしたまま
ビルドしないようにだけ注意してください。
私は何度もやらかして、あ゛ぁ゛!ってなってました。
前回から工夫した点とか
・SEやBGMの音量調整ができるようにした
工夫した点に書きましたが、
正直1週間ゲームジャムにコレ作らなくてよいと思います。
あったほうがよく作られているなとは思うのですが、
1週間しかないのでそれ以外のことに力を入れるべきかなと。
・タイトルや結果表示時にブラー効果を追加した(UIにこだわった)
ブラーを入れたことにより、
集中させたいUIがわかりやすくなりました。
これにより、ユーザーがどのボタンを押せばよいのかも分かりやすくなり、
後ろにオセロが表示されているのでどういうゲームなのかも
すぐに理解させることができるようになりました。
見せ方という点では絵が描ける方であれば、
その絵を作品に入れることで面白いゲームができると思っています。
が、私は絵は全く書けないので、
見た目面白くなさそうなものができてしまうことが多いです。
(多分同じようなエンジニア多いと思います)
そんな時は、描画に対して効果をつけたり、
面白いと思うゲームのUIを参考にするのが非常に良いと思います。
完走した感想
前作(下参考)に引き続きまた対戦ゲームを作ってしまいました。
絵心神経衰弱では絵が下手な状態を
「面白い」という状態に昇華することができたと思います。
今回のリアルタイムオセロではどこに置くか、いつ置くかの
駆け引きを「面白い」と思ってもらえるかなと思ったのですが、
テストプレイしてくれた親友に「連打ゲー」では?
と指摘を受け、置いた後の置けなくなる時間を長くするなどしました。
まだまだ改善の余地があると思っています。
次作るゲームとかによくなかった点は生かしていきたいと思います。
最後に
ゲーム作りで楽しいと思える瞬間は、
誰かが自分の作ったゲームをやって、
「面白い」と言ってもらえた時ではないでしょうか?
ぜひぜひ Unity Roomに投稿して遊んでもらいましょう!
この記事が気に入ったらサポートをしてみませんか?