Boss Roomいじり1:メインメニュー

Boss Roomをいじっていて、

シーン管理が知らない形になっていました。

まずHierarchyタブにStartupシーンだけ読み込まれていて他のシーンは見えず、

Assets > Scenesの中にMainMenuやらCharSelectなどの他のシーンが

格納されていました。

ビルドするときのシーンの一番上はStartupシーンなので、

ゲーム開始時にはStartupシーンが読み込まれるはずですね。


それで、ゲームスタートするとStartupシーンではなく

MainMenuシーンに移行していて「なんでStartupシーンじゃないの?」と思ったのですが、

Startupシーンの一番上(たぶん意識的に一番上に置いてくれている)に

ApplicationControllerという重要そうなオブジェクトがあるので見てみると、

ApplicationController.csというスクリプトが貼られていました。中身の一部は


こんな感じになっていて、確かにStart関数の中の最後に
SceneManager.LoadScene("MainMenu");
とありますね。なので、本当にStartupシーンは読み込まれているんだけど、
一瞬でMainMenuシーンに移行しているわけですね。

ここから読み始めたら中身がわかりそうです。
と思って中を読んでみましたが、何一つわかりません。
どうやらここは触らず、このまま使えばいいのかもしれません。

ここで重要なのは、
BossRoomというゲームに直接関係あるもの(キャラクターとか)はすくないです。
ただし、GameDataSourceというGameObjectがあって、
そこにエモートなどが登録されているようです。
また、ConnectionManagerというオブジェクトに
Assets/Scripts/ConnectionManagement/ConnectionManager.cs
というスクリプトがあり、部屋の最大人数
MaxConnectedPlayers = 8;
を設定しています。もし増減したかったらここをいじるべし。


そんなわけで、移った先のMainMenuシーンを見てみます。
色々ありますね。

【MainMenuState】
2つスクリプトがアタッチされています。
・Network Object.cs:
これはLibrary/PackageCache/com.unity.netcode.gameobjects@1.7.1/Runtime/Core/NetworkObject.cs
なので、いじらないやつです。たぶん。
・ClientMainMenuState.cs:
これは
/Assets/Scripts/Gameplay/GameState/ClientMainMenuState.cs
なので、ゲームに関わりが深いです。中身を見てみましょう。

開いたらすぐこれが実行されます。
基本的にはロビー参加に関係ある処理をやっているようです。

TrySignIn()関数はこういう内容のようです。
profileを参照しているので、キャラクターをいくつか管理するようなゲームだと
この辺りが必要なんでしょうか。
実際BossRoomにもprofileを変更する機能が最初からついていますので、
この辺りを応用すればいいのかも。

"Start with Lobby"ボタンを押したらロビーのUIを開く関数はここで定義しています。
実際対応するボタンにこの関数が入っていました。


【MainCamera】カメラ。
【UI Canvas】UI関連のキャンバス。2Dの時もこれは必要。
【EventSystem】これはそのまま。
【ThemeMusicStarter】音楽関連。これもこのまま。


【CharSel_Background】
UI以外の、背景。BossRoomでは様々な3Dのオブジェクトを置いている。
私の場合、完全に2次元のものに差し替える対象。


【Directional Light】ライト。これは2Dの場合要らない。
【PostProcessing】カメラにエフェクトをかける機能。
2Dの場合もあるかもしれないが、私の技術レベル的にこれは後回し。
【SettingsPanelCanvas】音量設定などのUIパネル。


そういうわけで、MainMenuシーンで私がいじる必要があるのは
【UI Canvas】
【CharSel_Background】
の2つがメインのようです。他はそのまま使える。


??? DontDestroyOnLoad ???
ここで一つ気になることが。
シーンを一つずつロードした時は上記のobjectたちが用意されていますが、
実際にゲームを起動した場合、MainMenuシーンとは別に
DontDestroyOnLoadというシーンがあります:

StartupシーンにあったManagerたちが残っています。
これはどういうことなのか調べてみました。
シーンをまたいで存在するゲームオブジェクトを作りたくなる時に使うもののようです。
DontDestroyOnLoad(シーン遷移時に破棄したくないゲームオブジェクト)
とすればシーンを跨いでも残るようです。
試しにStartupシーンにあるGameDataSourceオブジェクトにアタッチされている
Scripts/Gameplay/GameplayObjects/RuntimeDataContainers/GameDataSource.cs
の一部を見てみると、
と確かに
DontDestroyOnLoad(gameObject);
の記述がありますね。
参照すべきゲームデータをずっとロードしておく、ということなんですね。


なんとなく流れはわかってきました。


【2Dキャンバスを追加】
これで完全に2DバージョンのMainMenuシーンが作れるのか、試してみました。
MainMenuシーンをコピーし、MainMenu2Dというシーンを作りました。
そして、【CharSel_Background】(←3Dグラフィックのタイトル画面背景)以外を残して、
Canvas_backgroundというキャンバスを作り、適当にテキストを置きました。
左上、右上、左下、右下というテキストを置いてみました。
こんな感じでシーンを作りました。(非表示にしているオブジェクトは本当は表示ONにするべし)
また、StartupシーンのApplicationController.csのシーン移動のところで
SceneManager.LoadScene("MainMenu");
SceneManager.LoadScene("MainMenu2D");
と変更します。
こうすると、今まで表示されていた3Dグラフィックの背景は表示されず、
先ほど追加したCanvas_background、つまり4つのテキストが表示されるはずです。
やってみましょう。
(注意:新しくシーンを追加したときはちゃんとビルドセットに追加すること)

想定通りです。こうしたからって特に何もないのですが、
自分が理解した通りに動いてくれるとうれしいですね。


【シーン移動の確認】
最後に、MainMenuシーンからロビー作成してCharSelect(キャラクター選択)シーンに
移るスクリプトの確認をしておきます。
MainMenuシーンのHierarchyの中の
MainMenu UI Canvas > LobbyPopup > Tabs > LobbyCreationUI > Create Lobby Button
に、スクリプト
Scripts > Gameplay > UI > Lobby > LobbyCreationUI.cs
らしきものがアタッチされていますが、実際はLobbyCreationUIというprefabがアタッチされており、そのOnCreateClickという関数がアタッチされています。
その内容は
public void OnCreateClick(
{m_LobbyUIMediator.CreateLobbyRequest(m_LobbyNameInputField.text, m_IsPrivate.isOn);}
という感じで、謎の関数を呼んでいます。
てっきり私はここで
SceneManager.LoadScene("CharSelect");
と書かれているものだと思っていたのですが、予想外でした。
ところが、よく考えてみると
これはオンラインマルチゲームなので、
軽々しくシーン移動をできるはずもないので、
色々とやることがあるんだと思います。
その辺はあまり理解していませんが、この辺りの構造を触らずに読み込むシーンを
変えたいと思った場合、どのようにするのかを考えます。

Unixコマンドでgrepという便利なコマンドがあるので、
$ pwd
(HOGE)/com.unity.multiplayer.samples.coop-main/Assets/Scripts
$ grep -lr CharSelect ./
./ConnectionManagement/ConnectionState/HostingState.cs
./Gameplay/GameState/ClientCharSelectState.cs
./Gameplay/GameState/GameStateBehaviour.cs
./Gameplay/GameState/NetworkCharSelection.cs
./Gameplay/GameState/ServerCharSelectState.cs
./Gameplay/GameState/ServerPostGameState.cs
./Gameplay/UI/UICharSelectClassInfoBox.cs
./Gameplay/UI/UICharSelectPlayerSeat.cs
と出て、特にその中でも
./ConnectionManagement/ConnectionState/HostingState.cs
./Gameplay/GameState/ServerPostGameState.cs
の中の
SceneLoaderWrapper.Instance.LoadScene("CharSelect", useNetworkSceneManager: true);
は"CharSelect"シーンを呼び出しているので、
ここを例えば自分の作った別のシーン"CharSelect2D"とかにすれば、
別のシーン読み込みになるはずです。
(注意:新しくシーンを追加したときはちゃんとビルドセットに追加すること)


メインメニューのロビー機能はそのまま使うので、
次はBossRoomでいうところのCharSelect(キャラクター選択)シーンを
変更してみる記事を書きます。


【参考】



コメント

このブログの人気の投稿

【TopDown Engine】見下ろし2Dアクションゲームのためのアセット

初投稿

【コルーチン】処理順を大事にしたい時、処理を待ちたい時に使うコルーチンについて