Unity

【Unityでオンラインゲーム】Photonサーバーを用いたルーム・ロビーの作り方【即使えるコードも公開】

本記事内には、アフィリエイトリンクを含む場合があります

Unityでは、個人でもオンライン対戦ゲームを作ることができます。

特に、ここでは”Photon”というサーバーを用いる方法を紹介します。

原理をしっかり学ぶ前に、
まずは実装したい!という方の助けになるかと思います。

1.作るモノ

サーバーにログインし、ルーム作成とルーム一覧をみる機能を実装する方法です。

触って試してみてください↓

このようなログインとマッチングシステムは、
オンライン対戦ゲームでは、なくてはならないものですよね?

わざわざシーン移動せず、Panelを切り替えて行います。
ゲームの流れは次のような形です。

1 ニックネームを決めてログイン

特定のデータを保存しながら遊ぶゲームもありますが、
ここでは、毎回ニックネームを決めて遊ぶ、シンプルなゲームを想定します。

ニックネームを決めて、ログインボタンをクリック。

2 遊ぶルームを決める

ルームとは、ゲームシーンを共有するグループです。

Photonサーバーを無料で使う場合、同時接続数(CCU)の上限は20です。
これはルームでなく、ロビー全体の人数を指します。
ユーザーが増えるようであれば有料プランを検討しましょう。

ルームを決めるのに、ここで3つの選択肢を与えます。

●ルーム作成
●ランダムプレイ(ルームがなければ、自動ルーム作成)

とにかくすぐに遊びたい人向け(俗にいうクイックプレイ)
●ルーム一覧
すでに知り合いがルームを作っている場合などは、ここからルームを探します。

3 ゲームをはじめる

ルームでは、その部屋に入るのが早い人がルームホストとなります。
ルームホストがゲームをスタートさせることができます。

 

それでは、Scriptの内容を中心に、
ロビー・ルーム・ゲームスタートまでを作っていきます。

2.宣言と必要なUIを作る

第一に、Projectファイルにて、LobbySceneという名のSceneを作ります。

「LobbyManager.cs」のC#scriptを作成し、空のGameObjectにアタッチします。

Scriptでは、まず下図のように必要なモノを宣言するので、
それを参考に必要なUIオブジェクト(TextやPanelなど)をシーンに作成します。

*Prefabは別途作成したテンプレのようなオブジェクトです。
次の要素をもつオブジェクトを作り、Resourcesフォルダに入れておきます。

シーンに配置するオブジェクト、LobbyManagerのInspectorは次のようになります。

3.処理をひたすらコーディング

シーンに必要なオブジェクトを作成したら、
Scriptに各種処理をコーディングしていきます。

(#region~#endregionで区切ります)

Unity Methods

まずは、通常のUnity Methodsです。


Start()で初めの画面を表示、
その時点のルームやプレイヤー情報をDictionaryというListに格納させてます。
AutomaticallySyncSceneで、MasterClient(ルームホスト)のロードするゲームシーンをルーム内の他Client(ユーザー)に共有されるようになります。

UI Callbacks

UI Callbacksでは基本的に、UIのButtonで呼ぶメソッドを記載してます。
その際に、どのような処理をさせるかを記載します。

OnLoginButtonClicked()は、「ログイン」ボタンで呼び出します。
入力されたニックネームをPhotonNetworkに送り、設定します。
入力がない場合、エラー(invalid)を返します。

OnCreateRoomButtonClicked()は、「ルーム作成」ボタンで呼び出します。
ルーム名が入力されなければ、Room●●●(1000~10000の番号が入る)として、
最大プレイ人数MaxPlayers(数字のみ)をroomOptionsに送信。
PhotonNetworkサーバー上に、roomNameとroomOptionsをもったルームを作成します。

OnCancelButtonClicked()は、「キャンセル」ボタンで呼び出します。
1つ前のGameOptions(3つの選択肢のある)画面のみをActiveにして、戻ります。

 

OnShowRoomListButtonClicked()は「ルームリスト」ボタンで呼び出します。
ロビーにいなければロビーに入り、ルームリストの画面をActiveにします。

OnBackButtonClicked()は「戻る」ボタンで呼び出します。
ロビーから出て、前の画面をActiveにします。

OnLeaveGameButtonClicked()は「退室」ボタンで呼び出します。
ルームを出ます。

OnJoinRandomGameButtonClicked()は「ランダムプレイ」ボタンで呼び出します。
画面を切り替え、ランダムに取得されたルームに入る、
または、自動でルーム作成の処理(PhotonNetwork.JoinRandomRoom)が行われます。

OnStartGameButtonClicked()は「ゲームスタート」ボタンで呼び出します。
押した人がルームホスト(MasterClient)であること確認し、
設定の”GemeScene”をロードします。

Photon Callbacks

本丸といえようPhoton Callbacksです!

サーバーに情報を送信すると、自動的に実行されるメソッドであり、
そのときに処理してほしい内容を記載します。

Debug.Logを置くことで、そのメソッドの実行有無を確認でき、
エラーの原因を知れるようになります。
(ゲーム開発が終わったら、デバッグは除きましょう)

少し長くなりますが、テンプレみたいなものだと思って、
意味を理解して、必要な箇所のみアレンジして使えばよいでしょう^^

OnConnected()でネットへの接続、
OnConnectedToMaster()でPhotonサーバーへの接続がなされたことを確認できます。
(Debug.Logが読まれたならば)
LocalPlayer.NickNameは、自分が入力したニックネームの情報です。

サーバー接続と同時に、GameOptionsの画面を表示させます。

OnCreatedRoom()でルームが作られたことを確認します。

 

OnJoinedRoom()は、ルームに入ったときに読まれるメソッドです。
このときにルーム内のPanelをActiveにし、
自身がルームホスト(MasterClient)であれば、startGameButton(「ゲームスタート」ボタン)が表示されるようになります。

roomInfoText.textに、"ルーム名"、"現在のプレイ人数&最大プレイ人数"という情報を渡し、表示させます。

次に、ルーム内にいる各プレイヤーに対して
playerListPrefab(プレイヤーカードみたいなもの)を生成して
playerGameObjectという変数に入れ、
playerListContentを配下に並べられ、表示されます。

さらに、各プレイヤーのActorNumber(ルームに入ると割り当てられるID)が読まれ、
自分(LocalPlayer)であるかどうかを判別し、PlayerIndicatorの表示を判断させます(この機能は別になくても困らない^^;)。
ルームにいるプレイヤーをActorNumberという番号と紐付けて、記憶します。

最後にplayerGameObjectsというListに、これらActorNumerとplayerGameObjectをセットで格納しておきます。

 

OnPlayerEnterRoom()は、すでに自分がルームにいて、他のプレイヤーが入室したときに呼ばれます。
OnJoinedRoom()と同様、
roomInfo.textの更新、playerListObjectの生成と整列、ActorNumberによる自分の識別、Listへの格納を行います。
後からプレイヤー入室しても、ルームホスト(MasterClient)は変わらないので、「ゲームスタート」ボタンの表示有無に関する処理はありません。

OnPlayerLeftRoom()は、ルームから自分以外のプレイヤーが退室したときに呼ばれます。
roomInfo.textの更新、退室したプレイヤー(otherplayer)をListから削除します。
ここで、自分がルームホストであるかのチェックをさせます。

 


OnLeftRoom()は、自分が退室したときに呼ばれます。
GameOptionsの画面(Panel)をアクティブに、
playerListGameObjectsという配列データは削除され、空になります(どこかに入室したときにまた更新される)。

 


OnRoomListUpdate()は、ルームを一望できるロビーに入ったとき(JoinLobby)に呼ばれます。
現存するルーム、つまり
RoomInfoというクラス型のroomListという名のListに格納されているroom)を
1つずつ検証して有効なルームを精査し、
cachedRoomListというListに格納されていきます

さらに、cachedRoomListに格納されている各roomに対して、
roomListEntryPrefab(これまたカードみたいなもの)を生成、roomListEntryGameObjectという変数に入れ、
roomListParentGameObjectを配下に、並べられます。

それから、roomEntryGameObjectに、roomがもつ情報を反映させていきます。
最後に、roomListGameObjectsというListに格納されます。

Listが3つも登場するので、混乱するかもしれません^^;
イメージは次のようなものです。

全roomをもつList(roomList)
 → 有効なroomのList(cachedRoomList)
   → roomの情報が反映されたオブジェクトのList(roomListGameObjects)

 


OnLeftLobby()は、自分がロビーを出たときに呼ばれます。
ルーム一覧の情報は破棄され、
cachedRoomListに格納された情報も削除されます。

OnJoinRandomFailed()は、現存するルームに入室できなかったときに呼ばれます。
「ルーム作成」ボタンで呼び出したときと同じようにルーム作成の処理が行われますが、
ここでは設定画面をとばし、
コードの内容(ルーム名:Room ●●●●、最大プレイ人数:20)でルームが即作成されるようにしています。

Private Methods

サーバーの情報をもってきて、ローカルで呼ぶメソッドです。


OnJoinRoomButtonClicked()は、「Join」ボタンで呼び出します。
Photonoサーバーにおけるロビーからルームに移動する一連のメソッドを呼びます。

ClearRoomListView()は、Photon CallbacsのOnLeftLobby()で呼ばれます。
ルームを一覧に表示させていたroomListGameObjectsの中身を削除します。
(OnLeftLobby()では、cachedRoomListは削除される)

Public Methods

各種コードより、飛ばれるメソッドをここに記載します。


ActivePanel()は、画面切替を操作させるものです。
呼び出す際は、ActivatePanel(~.name)というように記載します。

初期画面(Login_UI_Panel.name)
ログイン後画面(GameOptions_UI_Panel.name)
ルーム作成画面(CreateRoom_UI_Panel.name)
ルーム内画面(InsideRoom_UI_Panel.name)
ロビー画面(RoomList_UI_Panel.name)
ランダムルーム検索中画面(JoinRandomRoom_UI_Panel.name)

 

以上
これはあくまで、私個人の理解に基づくものであることをご留意ください。

私がプロフェッショナルでないからこそ、
初心者にもわかりやすい説明になったかな?と思いたいのですが・・・^^;

サーバーに関して独学は、とても難しいですね。

4.コピペ用コード

以下は、コピペして使うのにご活用ください↓

 

InputFieldで、
ニックネームやルームの日本語入力
プレイ人数設定での半角数字のみを受け付けるようにする方法は
次の記事で紹介しております。

【UnityでWebGL問題】InputFieldで日本語入力を可能にする&スマホでの入力を可能にする方法今回は、"WebGL"でゲームをビルドしたときに起こる InputFieldに関する問題の解決方法を紹介します。 WebGLに生...

特にWebGLでゲームを出力した場合、
日本語に関してさまざまな問題が発生するのです。

ま、日本語をそもそも使わなければよい話なんですけどね^^;

ABOUT ME
いなも@システマライフハッカー
”仙豆”を開発することを夢見て、健康食品会社で働いていたものの、2016年に出会ったロシアの武術”システマ”こそ、その糸口があると感銘し、勝手にシステマ普及活動を始める。 一方で、クリエイティブなモノ作りが好きで、DX社会で楽しみを見出せる"Unity”を活かして、”スマートかつ快適な暮らし”のヒントを発信している。

COMMENT

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

CAPTCHA