『ペルソナ3 リロード』自動プレイ機能で約300人日のQA工数を削減。収集したログから導く「おすすめ行動」でプレイヤー挙動を効率的に再現する【CEDEC2024】

2024.09.02
CEDEC注目記事ゲームづくりの知識ゲームの舞台裏講演レポートCEDEC2024QA
この記事をシェア!
Twitter Facebook LINE B!
Twitter Facebook LINE B!

2024年8月21日(水)から8月23日(金)までの3日間、国内最大規模のゲーム業界カンファレンス「CEDEC2024」が、パシフィコ横浜ノース会場とオンライン会場のハイブリッド形式で開催されました。

本稿では、株式会社アトラスのペルソナチームからチーフプログラマーの埜渡 貴裕氏が登壇し、2024年2月1日に発売された『ペルソナ3 リロード』の開発に用いられた自動プレイ機能の概要が解説された講演「ペルソナ3 リロードでの自動プレイの実装と運用」の内容をレポートします。

TEXT / ハル飯田
EDIT / 酒井理恵

目次

自動プレイ実装の3つのコンセプト

本講演に登壇したのは「ペルソナ」シリーズを手がける株式会社アトラスの埜渡 貴裕(のわたり たかひろ)氏。『ペルソナ5 ザ・ロイヤル(以降、P5Rと表記)』ではメインプログラマーを務め、システム以外にもダンジョンや街などの「フィールドパート」を担当。『ペルソナ3 リロード(以降、P3Rと表記)』ではテクニカルサポートとして開発環境整備や自動プレイ実装に携わっています。

2007年のアトラス入社以降「ペルソナ」シリーズに携わり続けている埜渡氏

今回の題材となる『P3R』は2006年発売の『ペルソナ3』のフルリメイク作品で、開発にはUnreal Engine 4.27を使用しています。

資料については先行して開発していたPS4版日本語バージョンのものを使用

そして『P3R』の開発で使用されたのが、今回のテーマである「AIによる自動プレイ」の機能。埜渡氏によれば「ある程度考えてプレイしてくれる、botと呼ばれるイメージに近いもの」とのこと。
「ペルソナ」シリーズは通常プレイに100時間以上が想定されるボリュームのため、想定されるQA工数が膨大でした。特に、前作『P5R』の開発終盤は、開発環境の大規模化に伴ってQAだけでは十分なチェックができなくなりつつあったことから導入に至りました。
自動プレイを担当したのは僅かプログラマー2名という小規模チームであり、最少人数で最大限の効果を発揮させるため、以下の3つのコンセプトが立てられました。

  1. 自動プレイが原因でゲーム本編作成を妨げないこと
  2. なるべく汎用的にさまざまなチェックができるようにすること
  3. データや仕様の変更になるべく影響されない形にすること

自動プレイ対応のために新しい実装をお願いしない

    QA効率を高めるための自動プレイがかえって作業の遅れや不具合につながらないよう、差し込み作業は自分自身から、影響が出ない範囲に留め、余分な作業を増やさないことを心がけました。

    ゲーム本編ではロジックエラー発生時にassertやabortを入れてゲームを強制停止させているところも、自動プレイはフェイルセーフとなるような実装を行って自動プレイ側のプログラムの不備でゲームが停止することがないように実装しています。

    さまざまなチェックを網羅できる汎用性

      デバッグで“人間が考えたり思いつく範囲の不具合”は発見できるものの「そんなタイミングでそんな操作する?」という予測できない条件での不具合が発見しづらいという経験から生まれたコンセプトです。レアケースのバグに遭遇できるのは「たまたま条件が一致した場合」だったと埜渡氏は言います。

      このコンセプトに対応するため、自動プレイでは疑似的にゲームパッドの入力をオーバーライドする仕組みになっていますが、フィールドパートを除いて、このボタン入力にランダム性を含んだ状態で実装。いわゆるモンキーテストに近い実装にしました。毎回異なる操作を入力することで簡単には想定できないパターンを自動プレイで再現可能にしています。

      しかし、完全なランダムではメニュー画面など操作階層が深いところでは効率的でないため、ときには「メニューを開いてアイテムを指定したキャラクターに使う」という決め打ち行動も実装。これらのハイブリッドな実装によって「汎用的なチェック」ができるシステムを構築しています。

      完全ランダムでは階層が深くまであるメニュー画面で、特定の項目を開いたり閉じたりを繰り返す無意味な行動になってしまいがち

      仕様や実装の変更に強い設計

      ゲーム内の仕様に深く依存する形のデータでは開発データ側が修正されるたびに対応が必要になってしまいます。

      そこで、仕様や実装の変更に強い設計にも着手。これによって運用の柔軟性が上がるだけでなく、自動プレイ専用のデータを作る人的工数が削減されるという効果もありました。

      ベースから応用までの実装内容

      これらのコンセプトを踏まえて作成された『P3R』の自動プレイ。ここからは以下の4項目で解説された細かな実装内容をみていきます。

      • 自動プレイ本体のベースの実装
      • 自動プレイのコマンドによる操作の拡張
      • 自動プレイ中のログ収集
      • 自動プレイを利用した自動テスト

      自動プレイ本体のベースの実装

      次回作以降での使用も想定し、キー入力・カメラの座標取得などアプリケーションに依存しない部分はプラグインとして設計しました。また、アプリケーションに依存する部分はデバッグ用モジュール内に作成することで製品版ではモジュールごと取り外せるようにしています。アプリケーション用モジュールとの連携はUE_BUILD_SHIPPINGで囲うかマクロ関数でラップするなどの処理をすることで、製品版には一切残らない仕組みです。
      また、テストの信頼性を高めるために「移動先座標の直接指定」や「メニュー画面のカーソル位置の直接変更」など人間では不可能な操作は行わず、ゲームパッドからの入力のみとなっているのも特徴です。

      任意のキーの入力にはアンリアルエンジン(以降、UEと表記)のPlayerControllerクラスのInputKey、InputAxis関数を使用しました。

      こうした全体・共通処理は、ゲームに常駐させるためGameInstanceSubsystemの実体を用意し、細かな処理は「パート」という単位で個別に分けて実装しています。

      『P3R』の自動プレイではこの「パート」が全部で37種類実装されており、うちメニューやショップなどUI関連のものが30近くを占めています。パートには優先度が設定されているので、あるパートの実行中に別パートが有効になった場合でも優先度の高いパートのみが実行されます。

      この方式では実行されているパートが必ず1つだけになるので実行場所の把握が行いやすく、優先度も配列を変えるだけで管理できるというメリットがあります。細分化するほど専用の処理が実行できてパート単位での調整ができる利点もありますが、埜渡氏いわく「共通する修正が発生すると対応数が多くなり、分けたものの結局同じ処理しかしていないパートができてしまうこともあった」というデメリットも感じていたそうです。

      パートの設計はほとんどが“その画面で効果のあるボタン”をランダムで押す仕組みになっています。例えば、メニュー画面であれば方向キー・決定ボタン・キャンセルボタンなど、イベント画面であれば、スキップするボタン・バックログを開くボタンなどです。
      しかし、バトル中とフィールドでの操作はランダム任せではゲーム進行が不可能なため、ルールに基づく操作を実装しています。

      イベントの多いフィールドパートの移動制御手法

      フィールドパートでは「予めパスデータを用意して目的地に向かわせる」というデータを用意するコストがかけられなかったため「コリジョンとの衝突を回避しながら目的地を検索し、見つかったら移動する」という専用の操作を実装。NPCや扉などゲーム中でアクセスすると反応がある箇所を「イベントヒット」として作成し、ここを検索する目的地としています。

      イベントヒットのActor座標を目指して反応のあるBoundsまで移動する仕組みに

      「イベントヒット」はアクセスするとゲーム内イベントが始まって別のマップに移動するなどゲームが進行する要素になっているため、移動の目的地に設定することで自動プレイでゲームを進行させる仕組みになります。

      検索時にはプレイヤーの前方範囲に対してスフィアで「衝突せずに直線移動で到達できるもの」を対象とする設定になっており、一度アクセスしたイベントヒットは数十秒の間は対象とならないようにすることで連続して同じイベントヒットへアクセスする現象を防止しています。

      また、フィールドパートでのプレイヤー移動には移動した履歴を残す「ヒートマップ」も実装。プレイヤーが訪れた位置に50cm立法のブロックを追加していき、数百秒ごとに消えていく仕組みになっており、イベントヒットが見つからない場合にはヒートマップが生成されていない場所に向かうことで「まだ訪れていない・しばらく立ち入っていない」エリアへと向かわせられるようになっているとのこと。

      直近でプレイヤーがいると濃く、しばらく訪れていない場所は薄く色づけて表示されるため「ヒートマップ」という呼称に

      キャラクター移動については「ナビゲーションシステム(ナビメッシュ)でイベントシステムまでのパス検索をすれば良い」というアイデアが一般的です。実際に埜渡氏も同様の考えから「ナビメッシュの結果をノードで受け取り、ゲームパッドへの入力で移動する」方式を導入し、ダンジョン内で宝箱や階段へのアクセスが指示できることを確認していました。

      しかし、ダンジョン中はパーティーメンバーがプレイヤーを追跡する際の制御や敵シンボルがエンカウントのためプレイヤーに向かっていく動きにナビメッシュを使っていたので接続ができましたが、ナビメッシュを使用していない場所ではパス検索が失敗してしまう状況に。

      緑で示されているのがナビメッシュ。教室の後方にいるNPCまでのパスがつながっていない

      そこでナビメッシュが使用できない場所ではヒートマップに隣接ブロックとの接続関係を保持することでパス検索をする手法を構築。ヒートマップは既に歩き回った場所にしか生成されていないという制限もあるため、プレイヤーの移動はこれらを組み合わせ、以下の手順を踏むことで自動プレイでも有効な目的地へと向かう制御を実現しています。

      1. 付近のイベントヒットを検索しながら移動
      2. イベントヒットがない場合はヒートマップのブロックがない場所を歩くように移動
      3. 一定時間目的地が見つからない場合は離れたイベントヒットへの「パス検索」を実施
      4. その際まずはナビゲーションシステムでパス検索して見つかれば移動
      5. 発見できなかった場合はヒートマップでパス検索

      ランダム操作で敵とのバトルパートをクリアさせるための実装

      完全なランダム操作でもレベル上げや難易度設定によってはゲームオーバーにならず進行させることは可能ではありますが、より動作のバリエーションを増やした検証ができるよう「バトルに勝利できる回数を増やす」ルールが決められました。

      さまざまな属性の攻撃を用いて戦う『P3R』では、以下の画像のような優先順位で行動を指示。

      状況判断での行動指示

      • 主人公のHPが少なければ、回復スキル・アイテムを使用
      • 戦闘不能の仲間がいれば、回復スキル・アイテムを使用
      • 仲間のHPが少なければ、回復スキル・アイテムを使用
      • 状態異常の味方がいれば、回復スキル・アイテムを使用
      • 味方のSPが少なければ、回復アイテムを使用
      • 弱点をつければスキルを使用
      • シフト(行動者の変更)で弱点がつける場合はシフトを使用
      • 味方への補助スキルが使えれば補助スキル使用
      • 敵への補助スキルが使えれば補助スキルを使用
      • テウルギア(特殊スキル)が使えれば使用
      • オラクル(特殊スキル)が使えれば使用
      • 範囲攻撃スキルが使えれば使用

      基本的には回復を優先しつつ、相手の弱点を突いて戦略的に有利になる行動を行うよう設定することで自動プレイがバトルに勝利できる仕組みを構築しています。

      移動やバトルでの“決め打ち”行動はコマンド操作で実行

      本作でのコマンドは「決定ボタンを押す」など直接的な入力単位のものではなく、「メニューを開く」「〇〇へ向かう」などの行動単位で、約60種類作成されたとのこと。

      実装はCommandManagerというインスタンスに集積して実行を管理し、実行に際しては各パートが個別に持っているCommandWorkerへと渡して実行処理を行う仕組みに。複数パートにまたがる処理でも一気に受け渡して実行処理をパート別に行うことで、ダンジョン内で「目的地に向かう」コマンド実行中にバトルが発生してしまっても、バトル後には移動コマンドの処理が再開できるようになっています。

      CommandManagerは複数パートにまたがる処理をシーケンシャルに積める

      自動プレイとしてあらかじめ決めておいた行動に導く技術を流用して、コマンドを記録してリプレイする機能も実装につなげています。

      リプレイ時には操作したスクリプトの記録をPython形式で保存し、実行の際にはJSON形式へと変換してTCP通信でスクリプトをアプリケーションへと送信する流れに。その後はCommandManagerからCommandWorkerへと送られる、自動プレイ時と同じ制御によって手作業を繰り返させる処理に成功しています。

      自動プレイ中のログを収集し、「おすすめ行動」の選出に活用

      こうしてクリアまで辿り着けるようになった自動プレイが実際にプレイした内容をチェックするため、開発チームではElasticsearchを用いたサーバーを用意してログを収集。移動したマップやアクセスしたイベントヒット、戦った敵など多岐に渡って情報を集め、KibanaのダッシュボードやWebページにまとめることでデータを可視化してチェックに役立てていました。

      ログを確認することで、チェックできている項目やチェックできていない項目の確認に使用しています。

      『P3R』の日付別コミュイベント発生ランクを可視化した表。仕様と異なる日付でイベントが発生していないか、高いランクのイベントが発生してしまっていないか、自動プレイでコミュイベントを網羅できているかの確認に使用

      そして埜渡氏ら自動プレイチームが今回の『P3R』の開発で実現したのが、このプレイログと前述のコマンド機能を使った「おすすめ行動サーバー」というシステム。

      これはランダムに行動する自動プレイによって集められた膨大なログを解析し、その名の通り“ゲームをスムーズに進行させるおすすめな行動”をコマンドとして送信して自動プレイに指示するシステムで、より細かく、それでいてその場の判断よりも効果的な行動を指示するために生み出されました。

      『P3R』では「コミュイベント」で「コミュランク」を上げたり、その進行のために必要となる「人間パラメータ」を上げるイベントがゲームを進行する上で大きな要素であるため、おすすめ行動ではそれらを優先して指示するように設定。例えば、条件に当てはまる「イベントヒット」をログから検索してコマンドを送信するほか、「イベントでは最も効果的な選択肢を選ぶ」「換金アイテムを随時売却する」といった効率的な行動もコマンドで実行させていました。

      右上のウィンドウに表示されているのがおすすめ行動サーバーとの通信結果

      おすすめ行動サーバーのデータフローは下図の通り。自動プレイの行動ログはログサーバーに送信して蓄積されます。「おすすめ行動サーバー」を使用して自動プレイする場合は、ゲーム内のコミュイベント発生日のログから「何をすべきか」を判断し、最もおすすめな行動を自動プレイへと送信しています。

      おすすめ行動サーバーは他にも特定の手順が必要なコミュイベントのための手順を踏ませる指示も実装しています。これにより「ダンジョンパートでの失踪者の救出」や「シャッフルタイムでの取得物の選定」などゲームをスムーズかつバリエーションを増やしながらプレイするための行動指示も実装に成功しています。

      本来こうした効率的なプレイを指示するためにはゲームデータ(データベーステーブルやスクリプトなど)を分析して把握する必要がありますが、プランナーによる細かな日付や条件の設定をすべて解析するのは困難な手法です。しかし今回紹介された仕組みは実際に自動プレイが「その日コミュイベントを行えたか」をチェックしているので非常に簡単な仕組みになっており、古いバージョンのログは使えなくなってしまうものの再収集のコストも高くありません。アプリケーションとは切り離して制御できるためデータ凍結後の変更がしにくい時期でも調整や変更ができるのもメリットです。

      終わりの見えないランダム性のあるテストも自動化

      実装に関する最後のトピックは「自動プレイを使用した自動テスト」について。基本的には本編をクリアするまでのプレイを想定した自動プレイ機能ですが、コマンド操作を組み合わせることで同じシチュエーションを繰り返すなど、手作業で確認していた部分の自動テスト化も可能になりました。

      組み合わせが有限などテストの終わりが見えているものはアンリアルエンジンのAutomationツールのTestを使用し、決まっていないものはテストを管理するActorを用意して実装しました。

      これらにより「ダンジョンのフロアを上りつづける」や「バトルで全スキルを使用する」、そして「全イベントの全選択肢を選ぶ」テストまでさまざまな項目で自動テストが実装され、QAのコスト削減につながったとのこと。

      講演では実例として、バトル後にカードを取得するシャッフルタイムで「実際に全種類のカードが引き当てられるか」を確認した自動テストの動画も紹介。こちらはデバッグ機能を使って主人公が一撃で敵を倒せるようにした上で、バトル後に発生するカードはランダムのままです。敵を倒し続けながらカードを選択していく様子が確認できました。

      動画で例に挙げられた自動テストは「約12秒で1周」という短い時間の繰り返しながらも、取得物のバリエーションが500種類あるため手動でやり切るには膨大な試行回数を要します。自動テストでも全パターンを引き切るため15時間を要したとのことで、パターン網羅のチェックなど単純な工程では大きな工数削減につながりました。

      およそ40人日の実装コストで300人日強の工数削減に貢献

      ここから講演は自動プレイの実装・運用スケジュールに関する解説へ。『P3R』の開発前半ではゲームの一部分がチェックできるアルファ実装での自動プレイ実装が目標となっており、細かな検証を経て無事に実装。そしてアルファ以降のスケジュール後半になると、これまでに紹介されたさまざまな機能実装を本格的に行い、QAチェックでも工数削減に貢献していました。

      実装にはプログラマー2名で300人日程度の作業だったとの計算で、埜渡氏は「『P5R』での実装と似た部分もありつつ、コマンド処理など新たな取り組みに時間を要した」と振り返りました。

      ランダム操作についてはかなり初期の段階から実装できており、これだけでもある程度ゲームが自動進行できるので十分な不具合報告が可能だったことも紹介。以降の本格実装に入ると細かな対応が必要で、特にUIパートは要素が増える度に問題なく動作するよう対応をしていたとのことでした。

      稼働のための運用機材はアルファチェックでは3台ほどでしたが、アルファ以降は夜間にスタッフの機材を借りるなど機材を増やして昼夜を問わず稼働していたため、大まかに見積もって月500時間以上も自動プレイが実行されていました。自動プレイでは120~150時間でゲームを1周クリアできる性能だったため、月に3、4周回程度のテストに成功していた計算になります。
      最終的には運用機材は25台と、ゲーム規模に対して台数が少なめではあるものの、初期から稼働していたのでかなりのチェックができたとのこと。

      自動プレイの運用にはJenkinsを使用。パッケージを作成して機材に自動でインストールし、自動プレイするという一連の流れをジョブとして平日夜に行うように設定しました。これにより、毎日最新の環境で自動プレイを実行できる仕組みを構築していました。

      実際に進行不可に陥ったシーン。通常はキャラクター周囲に表示されているメッシュの距離を取ってから会話する仕組みだった。しかし、追尾してくる仲間に話しかけた際はプレイヤーキャラと距離を取るスペースがなく、会話が始まらず止まってしまった

      そして自動プレイがハングアップや進行不可バグなど「一定時間操作を受け付けない」状態に直面すると不具合を認識してダンプファイルを作成し、サーバーへとアップロード。サーバーの更新はJenkinsが定期的に監視しているので、ダンプファイルのアップロードを検知すると不具合に対するチケット作成も行われます。重複した内容も含むものの合計で412件のチケットが報告されており、埜渡氏も「なかなかの件数が発見できたのでは」と一定の手ごたえを口にしました。

      開発の序盤から自動プレイを運用していた成果もあり、QA期間中の検出バグは20件程度と少なめに。また、QA期間では進行不可などユーザービリティに著しく関わる「S/Aランクバグ」と呼ばれるものの発見が168件に留まり、『P5R』で693件ものバグ発見があったことを考えると、自動プレイによる効果が少なからずあったと感じられる結果となりました。
      総括すると、自動テストの実装によるQAコスト削減結果は以下のようになりました。

      • 宝箱の中身チェック(予定工数 約200人日)
      • シャッフルタイム取得チェック(予定工数 約60人日)
      • 敵ドロップアイテムチェック(予定工数 約35人日)
      • 全スキル変化チェック(予定工数 約40人日)

        全パターンチェックなど自動テストの実装によってQAコストは大幅カットに成功。およそ40人日の実装コストで300人日強の工数削減に貢献しました。

        今後は機械学習も活用し、行動バリエーション増加も視野に

        最後に埜渡氏は今回の開発を振り返って「実現できなかった点」と、今後の対応案を紹介。

        まず「コマンドをPythonスクリプト形式で記録して再生する仕組み」が完成していたものの、利便性に乏しくプログラマ以外は活用できないものだったことを挙げました。ツール化してプランナーやQAスタッフが活用できるように対応し、今回は手が回らなかった「報告された不具合が同じ手順で再現できるか自動確認する」仕組みについても実装していきたいとのこと。

        また、今回はおすすめ行動サーバーは手作業で構築したもので、日常シーンやダンジョンなど一部のみでの活用となりました。しかし、LLMでスクリプトを自動で作成したり機械学習ベースで行動を最適化したりして、更に効率的な行動のバリエーションが追加ができれば、チェック可能な要素が増えてQAの作業効率も上がるのではとの見解も示されました。

        自動プレイからはアイテムやスキルの効果値など今回活用した以上に細かなログを収集して記録していたため、こちらも更なるチェックに使用できる可能性も示唆。「ダメージ計算値が実機と資料で違っていないか」というレベルまで調べられると手作業でのチェックが減り、更なる効率化につながるのではないかと語られました。

        そしてQA期間では誤字やモデルのめりこみなど、比較的影響が少ない「B/Cランクバグ」と呼ばれるものの対応が多くなりましたが、このような見た目の不具合は自動プレイでは検出できませんでした。今後は見た目のバグも不具合と判定できるルールや仕組みを考えていきたいとのことで、更なる改善への意欲が示されました。

        最後にはおまけとして、おすすめ行動サーバーを介した強化学習で、作中の最強ボス撃破にチャレンジした検証の内容も紹介。結果としてはPyTorchでの学習によって最終的には勝率30%以上にまで到達しており、この知見を活用すれば通常バトルでもロジックによる指示なく最適な行動を目指せる可能性もあるとのこと。

        全編を通じて長時間の稼働で『P3R』のQAを支えた自動プレイの実装ポイントと更なる可能性が紹介され、大規模開発におけるQA効率化の大きなヒントが示されるセッションとなりました。

        『ペルソナ3 リロード』公式サイトペルソナ3 リロードでの自動プレイの実装と運用-CEDEC2024
        ハル飯田

        大阪生まれ大阪育ちのフリーライター。イベントやeスポーツシーンを取材したり懐ゲー回顧記事をコソコソ作ったり、時には大会にキャスターとして出演したりと、ゲーム周りで幅広く活動中。
        ゲームとスポーツ観戦を趣味に、日々ゲームをクリアしては「このゲームの何が自分に刺さったんだろう」と考察してはニヤニヤしている。

        関連記事

        C++の最新動向と展望をチェック。C++の日本語リファレンスサイト「cpprefjp」メンバーの講演を、ゲームエンジン開発者がレポート&補足してみた【CEDEC2024】
        2024.11.27
        『SINoALICE ーシノアリスー』が『シノアリスだったナニカ』に移行するまで。アプリサーバーなしで7年間のプレイ記録を後続アプリへ引き継ぐ【CEDEC2024】
        2024.11.20
        『鉄拳8』全キャラクターの髪型から衣装、靴まで自由にカスタマイズ!量産のカギは“体格に合わせた変形”をランタイム側で行う独自の多重リグシステム【CEDEC2024】
        2024.10.24
        よく使うレベルデザイン用語を押さえて英語圏の情報もキャッチ!Intensity Graph、Blockout、POIsなど13用語を現役ゲームデザイナーが解説【CEDEC2024】
        2024.10.18
        『塊魂』サウンドから見る「愛のあるモノづくり」。音で『塊魂』を想起させるために企画・実行したこと【CEDEC2024】
        2024.10.09
        サウンド担当者が開発中タイトルの最新仕様を知るには?『ゼルダの伝説 ティアーズ オブ ザ キングダム』の“フラットなモノ作り”を実現した開発環境【CEDEC2024】
        2024.10.04

        注目記事ランキング

        2024.12.05 - 2024.12.12
        VIEW MORE

        連載・特集ピックアップ

        イベントカレンダー

        VIEW MORE

        今日の用語

        ブレンド(Blend)
        ブレンド 2つ以上のものを混ぜ合わせることを意味する英単語。 ゲーム制作においても、2つ以上の要素を特定の割合によって合成することを示す。
        VIEW MORE

        Xで最新情報をチェック!