Unity 6以降で利用できる Multiplayer Play Mode (以下MPPM)パッケージを使うことで、Unityエディターに加え最大3つのVirtual Playerを起動してマルチプレイ対応ゲームの動作確認を簡単に行えるようになりました。
とはいえ、複数のVirtual Playerウィンドウを切り替え切り替え操作するのは煩わしいので、Unityエディター上で動作するオートパイロットフレームワークを使って操作を自動化してみました。 使用したのは、株式会社ディー・エヌ・エーが開発・OSSとして公開している Anjin(com.dena.anjin)パッケージです。
題材には、Unity社が公開しているNetcodeサンプルの2Dシューター GalacticKittens を使用しました。MPPMとAnjinを組み込んだforkを公開しています。
前提バージョン
- Unity 6000.0.23f1
- MPPMパッケージ v1.3.1
- Anjinパッケージ
v1.7.0v1.8.0 - Input Test Helperパッケージ v1.0.1
GalacticKittensの修正
本題に入る前に、GalacticKittensを若干修正しました。詳細は割愛します。
- Unity 6へのアップグレード
- TextMesh Proアップデートに伴ない、TMP Essensialsの更新(再インポート)
- Physics 2DのGravity.Yを0に変更
MPPMの導入
MPPMはパッケージマネージャからインストールできます。 "Unity Registry" で "multiplay" で検索すれば見つかります。
インストールしたら、Window > Multiplayer > Multiplayer Play Mode でウィンドウを開き、Virtual Playerを有効化できます。
下図では、Editorだけに host
タグ、Virtual Playerに join
タグを付けています。
タグについては後述します。
Virtual Playerを有効化(チェックボックスをonにした後、表示が "Active" に変わる)した時点で、対応するVirtual Playerウィンドウが開きます。この状態でエディター側で再生モードに入ると、各Virtual Playerでもゲームが再生されます。
ここまでで、手動でマルチプレイの動作確認ができるようになりました。
Anjinの導入
Anjinパッケージのインストール
Anjinパッケージのインストールは、openupm-cli を使用して次のコマンドで行なうのが簡単です。
openupm add com.dena.anjin
Package Managerウィンドウによるインストール方法は、リポジトリのREADMEを参照してください。
GalacticKittensの追加修正(InputをDI可能にする)
続いて、GalacticKittens側のいくつかのクラスに修正を加えます。 GalacticKittensはキー入力判定にInput Manager (legacy) を使用しており、このままではAnjinから入力を操作できません。 そこで、Input Test Helperパッケージを利用してスタブを注入できるようにします。
Input Test Helperパッケージのインストールは、同様に次のコマンドで行ないます。
openupm add com.nowsprinting.test-helper
今回、Inputを置き換えたのは次の3ファイルです。
- Assets/Scripts/Managers/MenuManager.cs
- Assets/Scripts/Player/PlayerShipMovement.cs
- Assets/Scripts/Player/PlayerShipShootBullet.cs
いずれも、クラスに次のプロパティを追加するだけです。
public IInput Input { private get; set; } = new InputWrapper();
Input Test Helperパッケージについて詳しくは拙著『Unity Test Framework完全攻略ガイド 統合テスト編』第4章を参照してください。
オートパイロットの設定
Anjinの設定は、Sceneごとに操作を担当するAgentを割り当てることで行ないます*1。 設定のルートは Assets/Autopilot/Settings/AutopilotSettings ファイルで、これをInspectorウィンドウで開いて編集します。
今回は次のように設定しました(図はScene Agent Mappingのみ抜粋)。
Menu
カスタムAgent MenuAgent
を実装しました。
Menuには2つの状態があり、状態を見て振る舞いを変えています。
- "PRESS ANY KEY TO START"と表示されているとき:
MenuManager
の参照しているInput
にスタブを注入し、"ANY KEY" が押されている状態を返します。これで次の状態に遷移します。 - "HOST" か "JOIN" を選択:Virtual Playerに設定されているタグに応じて、"HOST" か "JOIN" ボタンをクリックします。タグは、
CurrentPlayer.ReadOnlyTags()
で取得できます。
CharacterSelection
ビルトインの UGUIPlaybackAgent
を使用して、"READY" ボタンをクリックします。
キャラクターは4種類いますが、マルチプレイヤーがJoinしたときに異なるキャラクターが選択された状態になっているため、そのまま変更せず次に進みます。
Gameplay
カスタムAgent GameplayAgent
を実装しました。
移動を行なう PlayerShipMovement
と、弾を発射する PlayerShipShootBullet
それぞれの参照している Input
にスタブを注入し、ランダムな入力を与えています。
自動プレイの目的が攻略であるなら、ランダム入力でなく賢いAIを実装したり、ML-Agents で機械学習エージェントを使います。
Defeat および Victory
ビルトインの UGUIPlaybackAgent
を使用して、"MENU" ボタンをクリックします。
Bootstrap および Controls
いずれも勝手に次のsceneに遷移するため、Agentを割り当てていません。
オートパイロットの実行
MPPMウィンドウでVirtual Playersの設定が済んだ状態で(ひとつは host
タグが必要です)、次の操作で実行できます。
- Assets/Autopilot/Settings/AutopilotSettings をInspectorウィンドウで開く
- 下のほうにある "Run" ボタンをクリック
これで再生モードに切り替わり、オートパイロット設定に従って自動プレイされます。 停止するには "Stop" ボタンをクリックします。
参考:Virtual PlayersでもAnjinが動作する仕組み
Anjinは起動状態を AutopilotState というScriptableObjectで永続化しています。"Run" ボタンをクリックされると、まず AutopilotState の状態が変わり、再生モードに入ります。 MPPMでは、再生モードに入るときにプロジェクトのファイルが共有されるため*2、Virtual Player側でも AutopilotState を見てオートパイロットが動き出します。
この仕組みのため、現状では次の制約があります*3。
- Editorは手動、Virtual Playerは自動、といった使い分けはできません
- Playerによって別々のシナリオ(AutopilotSettings)を割り当てることはできません
- 再生モード中にAutopilotSettingsの "Run" ボタンをクリックしたときは、Editorのみオートパイロットが起動します
[11/18追記]
AutopilotStateのファイル更新がされたりされなかったりするようで、Anjin v1.8から明示的に AssetDatabase.SaveAssetIfDirty
する修正を入れます。
またv1.8ではSlackReporterのメッセージを入力できるようになりますが、ここにタグを出力するプレースホルダも追加します。
参考:出力ファイル
各Virtual PlayerはMacOSの場合、プロジェクトルート/Library/VP/の下にユニークな名前のディレクトリが作られます。
Anjinの FileLogger
などの出力ファイルパスを相対パスで指定した場合、このVirtual Playerのパスが起点となります。
つまりVirtual Playerごと個別のパスに出力されます。
ただし、UGUIPlaybackAgent
が内部で使用しているAutomated QAパッケージは、スクリーンショットを Application.PersistentDataPath
に出力します。これは変更できません。
従って、MPPM環境下で UGUIPlaybackAgent
を使用すると、出力ファイル重複のエラーが出ます。
将来的にAnjinはAutomated QAパッケージ非依存になり、この制限事項は解消される予定です。
Play Mode Scenarios [11/18追記]
MPPMには、Virtual Playerでなくプレイヤービルド*4をローカルインスタンスとして起動するPlay Mode Scenarios機能もあります。 Play Mode Scenariosではタグでなく起動時引数を渡すことができ、インスタンスごとに別々のAutopilotSettingsを割り当てることも可能です。
ただし、Play Mode ScenariosはAutopilotSettingsの "Run" ボタンでは起動しないため、通常の再生モードを開始してから "Run" ボタンで(Editorのみ)オートパイロットを起動する必要があります。 また、タグはEditor側は1つしか選択できず、ローカルインスタンスには指定できません。 Virtual Playersとは使い勝手が異なるので注意してください。
Play Mode Scenariosについて詳しくは Test live instances locally and remotely | Unity Multiplayer を参照してください。
宣伝
冬コミ(C105)で、Anjinのあれこれを詰め込んだ『Anjin非公式ファンブック』を頒布予定です。夏から出す出す詐欺していましたが今度こそ間に合うはず。
表紙・挿絵は『江戸むらさき特急』の著者、ほりのぶゆき先生にお願いしました!
2日目 西う47b「いか小屋」でお待ちしております。 また、後日BOOTHでも頒布予定です。