【Unity1Week】オンラインゲームへの挑戦と難しさ
はじめに
ご無沙汰しております、putinuです。
かなり暑くなってきましたね、皆さんも水分補給など怠らず、熱中症には十分気を付けていきましょう!
さて、今回の記事では、先日(2022年5月2日~5月8日)開催された第22回Unity1週間ゲームジャムへ参加した際の感想や反省について述べていきます。特に、今回初めて取り扱ったPUN2に関してチャレンジしたことや苦労した点について詳しくお話していきますので、是非興味があればご一読いただけると幸いです。
Unity1週間ゲームジャムとは?
まずは、今回参加したUnity1週間ゲームジャムについて紹介します。
Unity1週間ゲームジャム(別名:Unity1Week, u1w)とは、naichi(@naichilab)さんが運営するウェブページunityroomにて開催されている、1週間でUnityゲームを作成するお祭りイベントです。
開催時に毎度お題が出題され、今回のお題は「そろえる」でした。執筆時点(5/31)では410作品ものゲームが投稿されており、初心者からプロ並みのクリエイターまで様々な方のゲームを楽しむことが出来ます。
初心者の方でも参加しやすく、とても賑やかで沢山の評価・コメントを頂けますので、興味のある方は次回のイベント時に参加してみることをおすすめします!
自分の作品について
Blockete
私自身も今回のイベントへ参加し、「Blockete」というタイトルで2人オンライン対戦型パズルゲームを開発しました。
オンラインゲームということもあり、あまり沢山遊ばれないだろうと予想していましたが、ぱふもどきさんのYouTube配信などを通して沢山の方に遊んでいただき、また沢山の評価を頂くことが出来ました。
この場を借りて、プレイ・評価・コメントして下さった皆様に感謝申し上げます。ありがとうございます!
評価
続いて、今回の評価についてさらっとご紹介します。
前回の作品「修正少年アメンダ」より評価は落ち、総合ランキング50位以内に入ることは叶いませんでした。
オンライン部分の実装に苦労し、他の部分にあまり手をつけられなかった点、発想のアイデアにあまり斬新さが無かった点などを考えるとまあ妥当でしょう。
しかし、コメントでは演出面を褒めて頂いたり、対戦が盛り上がったなど、とてもありがたいお言葉を頂きました。
また全体的に安定性が増してきたと捉えることも出来そうです。イベントに何度も参加している成果が出ているのかもしれません。
本題:オンライン実装
PUN2
では、本記事の本題であるオンラインに関するお話をしていきます。
まず、今回のオンライン実装に関しては、Photon Unity Networking 2(PUN2)と呼ばれる、マッチメイキングを実現するUnityパッケージを使用しました。
参考になるインターネット記事が多く、また最も名前を聞くというのが主な選択理由になります。
どんな部分に利用したか
マッチメイキング
ゲーム開始時のブロックの生成
ブロックの配置
以上の部分のみになります。
「ブロックを消した時」や「相手の体力を減らした時」には必要無かったのか、と思われるかもしれません。ですが、「ブロックを配置」したこととそのタイミングさえ分かっていれば、両者同じ処理を行うため必要ないのでは無いかと考えました。
当時の私は、可能な限りオンラインに関わる部分を減らしたいと考えていたためにこのような判断をしました。しかし、これが起因となって通信の遅延による受けるダメージ量の変化、また勝敗の変化を引き起こすことになりました。
PUN2では、クライアント全体の1秒当たりのメッセージ数が50回までに制限されており、この判断が正しかったのか、今でも答えを見いだせずにいます。
苦労したこと・難しかったこと
まず1つ目に、「PUN2に触れたことが無かった」です。
Unity1Weekへ何度も参加されている方や、1週間でのゲーム開発の難しさを理解されている方であれば、恐らくこの文を見た瞬間にびっくりすることでしょう。
1週間という制約がある中で、新技術に触れることは、思わぬバグやエラー、また投稿の遅刻を意味します。
十分な技術検証が行えていない状態で、勢いのみで押し進めてしまうと、後で痛い思いをすることになります。私自身もこれで一度Unity1Weekの参加を諦めたことがあります。
今回のUnity1Weekでは、1日目に使用したい機能の検証を全て行い、そこでダメそうならオンライン機能は実装しない方針で進めました。
結果として、ある程度実現が可能なことが判明し、2日目より実装に取り掛かりました。PUN2が簡単にマッチメイキングを実現することが出来るサービスでかつ、分かりやすい電子書籍があったことが救いでした。
以下の書籍は、私が開発時とても参考にしたo8queさんの電子書籍です。
2つ目は、「PunRPCの制限を詳しく理解していなかった」という点です。
1つ目に挙げた行動によって、後から影響をもろに受けて発生した問題です。
PunRPCは、そのAttributeをつけたメソッドを、通信が確立しているルーム内の全員に実行させるものです。
PunRPCを用いて通信部分を実装していた当時、私は送信時に送るデータの中身について全く考えていませんでした。そのため、メソッドの引数にユーザが定義したクラスやUnityのGameObject、Transformなどを含めていました。
しかし、PunRPCでは以上のようなデータはデフォルトでは送信することが出来ません。私ははじめこれを知りませんでした。まあ当たり前といっちゃ当たり前ですが。
問題を解決しようと、様々な記事やFAQを見て回った結果、「もっと適切な情報の渡し方があるのではないか」というアンサーを見かけ、そこからようやく理解・解決することが出来ました。
クラスなど、大量の情報を与えていた部分は、座標など、簡単な情報のみをやりとりするように変更したことでこの問題は解決しました。
代償として、かなり多くの時間を費やすこととなりましたが…。
後から考えてみれば、どれだけ大きな情報を送っているんだと突っ込んでしまいたくなります。最終的に完成したコードはとてもぐちゃぐちゃなものになってしまいました。
この問題が起こった原因は、始めに記したように、前情報なしに新技術に触れたことです。問題にぶち当たってしまった時、かなり長い時間立ち止まることになってしまうので、期間内の投稿を目指すのであれば、基本的には習得した技術のみで挑むべきでしょう。
私は当時、PUN2の勉強を兼ねて、と割り切っていたので遅刻に対してそこまで抵抗感はありませんでしたが、次回のUnity1Weekではしっかり期間内に完成させることを今回の反省を踏まえて目標にしたいと思います。
最後に、「乱数をお互いで同じ値を渡すこと」にも苦労したのでお話します。
これに関しては、完全に私の技術力不足というか、ひらめき不足だったと感じている点です。
本作では、ゲームスタート時にお互いにランダムにブロックを生成し、さらにそのブロックは両者とも同じものにする、という仕組みがあります。TETRISやぷよぷよで見かける、始めに見えるブロックは両者とも同じというあの仕組みです。
ここで生じた問題が、お互いで乱数を生成してしまったら、結果が異なってしまう!というものでした。
[PunRPC]属性をつけたメソッド内に記述しても、これはルーム内にいる全てのクライアントに同じメソッドを実行させるものなので、そこで生成される乱数はそれぞれ異なった値になってしまいます。
この部分の実装は、段階としてはまだかなり早い方だったのでPUN2に関する理解もまだ浅い状態でした。この部分の実装にもかなり時間を掛けてしまいました。
ですが、解決はとても簡単でした。
片側で乱数を生成し、そこで生成された値を全員に共有すればよかったのです。片側を取得するにはbool型の PhotonNetwork.IsMasterClientを使用することで実現できました。
おわりに
如何だったでしょうか。今回実装したオンライン機能について難しかった部分を述べ始めるとキリが無いため、本記事ではその中でも特に苦労した部分として3つ紹介させて頂きました。
ここまで様々な問題点や反省を書いてきましたが、PUN2という新技術をUnity1Weekに持ってきたことは決して失敗ではなかったと感じています。
確かに、何度も壁に当たることがあり、その度に大事な時間を浪費してしまいました。しかし、そこから得られた知識というものはとても大きなものであったと感じています。
大きく分けると、
PUN2に関連する知識
オンラインゲーム開発に必要な機能や技術
オンラインに関するバグ解決能力
以上の3つがある程度身に付いたと感じています。
もちろん、まだまだ知らないような機能や知識も沢山ありますし、今回のゲーム「Blockete」でも遅延問題は解決出来ていないままです。
今後またPUN2を使う機会が大学でありそうですので、これからもインプットを増やしつつ、時折しっかりとアウトプットしていけるよう努力していきます。
またShaderとかも触りたいですね!
ということで、ここまで閲覧いただきありがとうございました。
また今度、putinuでした。