『推理する面白さ』磨きに注力できるマダミス制作支援ツール、ミステリーラボを制作しました【GIFTech2025春 優勝】
この記事はGIFTech 2025 春の優勝受賞作品、ミステリーラボの紹介とPdMとして行なったことに関する記事です
アジャイル開発事例やハッカソン参加のモチベーション向上のためにお読みいただけると嬉しいです
ミステリーラボについて
マーダーミステリー制作における課題
みなさんは殺人事件をテーマにした体験型の推理ゲーム、マーダーミステリー(以下マダミス)をプレイしたことはありますか?
マーダーミステリーのシナリオ制作は創造性と論理性が高度に要求され、非常に複雑です
登場人物の設定、膨大な証拠品、入り組んだストーリーライン、そしてプレイヤーを欺くトリック、これらを矛盾なく組み合わせる必要があり、制作者はしばしば情報の整合性を取る作業に膨大な時間を費やします
特に、登場人物が増え、物語が複雑化するほど、人間によるチェックだけでは見逃せない矛盾が発生するリスクが高まり、制作コストも格段に跳ね上がります
今回担当させていただいたエンターテイナーであるこれからミステリーの飯田さんとかるらさんから制作の裏側を聞くまで、その大変さを知りませんでした…
何を解決したか
私たちはマーダーミステリー制作における「矛盾との戦い」というペインに着目しました
本プロダクトは、制作者がシナリオの骨子(登場人物、証拠品、タイムラインなど)を入力することで、AIがその情報間の潜在的な矛盾点を検出し、指摘する機能を提供します
これにより、制作者は「推理する面白さ」を磨く創造的な作業に集中でき、質の高いシナリオを生み出せるようになります
生成AIを活用することで、ルールベースでは捉えきれない複雑な文脈上の矛盾にも対応できる可能性を探り、Rule as Codeの概念と生成AIの掛け合わせにチャレンジしました
さらに、生成されたキャラクターとして振る舞うようAIエージェントに役割を与え、ゲームのテストプレイを行うことにも成功しました
ハッカソン開始前から差をつける
技術選定
今回のハッカソンはハッカソン開始日の前にチームが決まり、開始日にテーマが決まることもあったのでテーマ決定の前にエンジニア全員で技術スタックのすり合わせを行い、技術要件を整理した上でCI/CDが行われるように予め準備しました
当初は「テーマは分からないけどモバイルアプリでも作るのかな」といった雰囲気だったのでExpoの環境構築を行なっていましたが、テーマが決定した後はWebページとしてホスティングする必要があることが分かったのでExpoを捨ててRemixのCI/CD環境を作り直しました
バックエンドはFastAPIを使用し、AWS Lambdaにホスティングしています
ハッカソン開始前に構成したアーキテクチャはプロダクトお披露目会まで使われ続け、「MVP開発ならこれ以上のことは用意しなくていいよね」の状態を早期の段階で完成させていました
フロントエンドとバックエンドで選定した技術には全て理由があります
Remixを選定した理由
SSR可能なフレームワークであるRemixを使用することでクレデンシャルな値の秘匿が容易となり、さらに軽量なフレームワークであるためNext.jsを使用するのに比べてフロントエンドのパフォーマンスも向上します
Next.jsは重いと思っていることや、そもそもMVP開発であるためNext.jsの機能を使用する見込みがなかったので採用しませんでした
しかしAmplifyでのNext.jsデプロイは容易であるため、何を優先するかをチームで話し合った上でNext.jsをリリースするのはアリだと思います(RemixをLambda Web Adapterでデプロイするのに少し苦労しました)
また、クレデンシャルな値を扱わないページを作ることになっていたならばCloudFrontとS3での静的ページの配信を選んでいたと思います
Next.js不要論、自分にとっては納得感があります
MVP開発においてはRemixを使用する機会がかなり増えました
Jotai
Jotaiはグローバルステート管理ライブラリです
マーダーミステリーのゲーム情報一式をステートとして管理することでフロントエンド実装を機能ごとにチケットを分割でき、並行して進められるようにしました
FastAPIを選定した理由
スキーマ駆動開発がかなり容易になるという理由でお勧めしています
APIスキーマのドキュメント整備を行わなくて良いことや、リクエスト形式とレスポンスを予め決めてモックAPIを用意すればフロントとバックエンドの実装を並行して進めることが可能になります
FastAPIがあったおかげでバックエンド側の更新を即座にフロント側に反映でき、高速に開発を進められました
スキーマ駆動開発についてはこちらの発表で知りました
AWS Bedrock
Lambdaを経由してBedrockを使用する構成にしていましたが、Bedrockのレートリミット制限による可用性の低下に悩まされ、最終的にはAnthoropicのAPIを直で叩くようになりました
構造化されたデータをLambdaに投げ、キャラの行動の矛盾は生成AIで検出しています
Lambdaの中で生成AIのレスポンス待ちの時間を作ることに対し、コスト的にすごいもったいないと感じていたのでLambdaではなくStepFunctionを活用すればよかったなと思っております
あともっと時間があればAPI GatewayもRESTではなくWebSocketに切り替えたかった
キャラの時系列ごとの行動データをもとに矛盾の有無とその内容を判断
スプリントプランニング
ハッカソン参加メンバーの背景や、注力できる時間にばらつきがあることからGitHub Projectsでカンバンを用意してハッカソンを進めることについて合意形成を行なっていました
普段、人と話す上で"同じものを見て話す"ことを大切にしています
同じものを見て話すことで認識のズレは小さくなり、伝えたいことが伝わる可能性がグッと高くなると考えているからです
毎週のMTGではカンバンを画面共有しながら話すことを心がけていました
全員が同じカンバンを見流ことでチケットの担当者であったり、完了見込みはいつなのか等の共通認識を持てるように制作を進めることを意識していました
ハッカソン開始 ヒアリングから要件定義・チケット化まで
ヒアリング
今回はN1エンジニアリングだったのでこれからミステリーのお二人に「何に困っているのか」と「解決された状態とはどういった状態か」についてヒアリングさせていただきました
困りごとについても優先度を付け、何から取り組むかについてお二人とチーム双方で合意形成を取りました
お二人とも生成AIなどの技術に明るく、とても質問しやすかったです🙏
要件定義・チケット化まで
ヒアリングした内容をもとに要件定義まで落とし込んでいきます
ユーザストーリーマッピング→画面遷移図→データ構造やUI、機能
の順で逆算し、チケットまで落とし込みました
ハッカソン終了後に見つけたUX 5段階モデルのツイートがとても分かりやすかったのでこちらの方のツイートも共有します
普段の業務であれば下記を使用して非機能要件まで認識合わせを行いますが、ハッカソンでは不要だと思ったためここまでは行っておりません
チケットの大きさは"1週間未満で完了できる"ことを一つの単位としていました
言語化したチケットの粒度がどうしても大きくなってしまう場合については子issueとしてさらに細分化しました
ここまでがヒアリングからGitHub Projectsへのチケット化までの流れです
ハッカソン中盤 コミュニケーション
エンジニアとデザイナー間の連携
shadcn/ui
shadcn/uiを使用する方向で最初から合意形成を取りました
デザインに力を入れることを否定したわけではなく、エンジニアとデザイナー共に考えることを減らして判断に迷う時間を作らないために導入しました
デザイナーのゆうゆさんには@shadcn/ui - Design Systemを用いてFigma実装いただくようお願いしており、とても連携取りやすかったです
デザイン実装の進め方
Figmaデザインは要件そのものであり、エンジニアはそれに従うべきであるが、100%従うべきではない(CSS実装の大変さもあるので1px単位でFigmaデザインを完璧に再現するのは労力がいるため再現度98%より上の部分は雰囲気で合わせる)と思っています
アジャイル開発を行う最中、Figmaに忠実なCSSの記述よりも機能実装を優先したことは否めませんでしたが、その点に寛容でいてくれたことに感謝しております
機能実装が概ね完了した後にFigmaに100%忠実になるようにCSS実装に注力いただいたメンバーのおかげでUI/UXの完成度もかなり高まりました
スプリント最終週の2週間前まではFigmaへの忠実度は85%程度にして実装し、最後の追い込みで100%まで追い込むのはとても良い進め方だったと思っています
当初から「リリースの少し前まではFigmaデザインに対して実装は85%程度の再現にとどめ、機能実装を優先し、最後の追い込みで100%を目指す方法で進めるぞ」と決めていてもよかったかもしれません
繰り返される諸行無常
エンジニア間の連携
基本的には先述のスキーマ駆動開発でフロントエンド担当とバックエンド担当が並行して実装できたため、進め方はよかったです
また、コードレビューの依頼を受けた時も全員まず「実装ありがとうございます!」から言えたことも良いコミュニケーションでした
時代の流れに乗っている面白さでもあるのですが、AIにコードを書かせることで困ったこともありました
AIに書かせたコードをPull Requestする前に気をつけること
AIに書かせたコードをPull Requestする前にコミット内容は説明できるようにしましょう
自分がAIに書かせたコードをPRし、他者を困惑させたケース
ハッカソンでのMVP開発だったということもあり、「とりあえず動くようになったしいいか!」くらいの気持ちでPRを作成していました
コードレビューでは 「これって何が問題でどうやって修正したPRなんでしたっけ?」 とコメントされ、ハッとしました
AIにコードを生成させること自体は問題ありませんが、処理の流れと中身を開発者自身が理解している必要はあります
PRを作成する際はバグの原因や修正内容を正しく説明できるよう、理解に努めましょう
AIに書かせたコードを理解する必要性はこちらの記事でも説明されています
例えハッカソンでスピード重視だったとしても、コードの中身の理解をスルーしてしまうと結局チーム全体が「あれ? これ何?」な状態になってしまいます…!
自分がレビューを行なって困惑したケース
レビューしたコードにどう考えても不要な処理が多数含まれており、困惑しながら処理内容についてPR作成者に質問していました
レビューのためにコードを読み進めるたびに不要な処理が見つかり、一つ一つ「この処理は必要か」「APIレスポンスに不要と思われる値が含まれているがその意図は何か」といった質問を重ねてしまっていました
レビュイーは生成AIを使ってコードを書いていたとのことで指摘内容に関して私の意見に納得していました
後日、「あの時は鬼気迫っていた」とコメントされたので私の指摘の仕方も良くなかったと思います(自分のことは棚に上げておいて…)
このようなケースはレビュー文章を作成した後に少し寝かせ、文体を柔らかくしましょう
鬼気迫ると指摘を受けたのは自分がコードをレビューし、その多くの処理が無駄であったことから多少モヤモヤしながらコメントを作成し、そのまま送信したことが理由ではないかと考えています
コメント作成後は送信ボタンを押す前に少しPCから離れてリラックスした後に文章を確認し直すのが良さそうです
ハッカソン終盤 ピッチに向けた仕上げ
メンバーそれぞれの頑張りの甲斐があり、プロダクト自体はかなり仕上がっていたのでイベント1週間前には優勝をほぼ確信していました(実際にはどのチームも点数的にはほぼ同列だったため少し恥ずかしいです)
イベントに向けた詰めの取り組みとしてはピッチで使用するスライドや動画制作を行うほか、バックエンド処理の高速化やデザインの昇華にさらに時間をかけることができたので満足いく仕上がりになりました
そしてイベント当日はミステリーラボを体験した来場者から「生成AIってこんなことまでできるんだ!」という感想を多くいただき、多数の票を得て優勝できました🏆
おわりに
1ヶ月半駆け抜けたハッカソンでは多くの学びがあり、期間中に感じていたことを熱が冷めないうちに一気に書き上げてしまいました
優勝コメントでも残しましたが、従来の技術では難易度が高かったが、生成AIの台頭によってサービスの価値として組み込めるようになった要素は下記3点だと思っています
- 大量の文章をもとに回答を作成する作業を極めて短時間で実行できる
- さまざまな役割になりきることで自身に無い視点を与える
- 人が受け止めていた心理的負荷の代替
今回は1と2をプロダクトにうまく組み込めたと思っています
「とにかく生成AIを使え!」と叫ばれる世の中になりましたが、道具は適切に使い分けたいものです
1ヶ月半一緒に走り続けてくれたチームの皆にとても感謝しています
初めに決めたプロダクトの方針を信じて一緒に走ってくれたこと、そして優勝を伝えられた瞬間はとても嬉しかったです
本当に良いチームでした!
チームの皆やこれからミステリーのお二人、運営としてハッカソンの場を提供してくださったGIFTechの皆様、本当にありがとうございました!
Produced by TeamB
工藤
バックエンド担当 初ハッカソンの賑やかし担当。
高窪
バックエンド担当。新卒研修サボりながらハッカソンの開発してた。
島﨑
フロントエンド担当 動いたら天才、バグったら経験値
ゆうゆ
UIデザイン担当。エンジニア陣がかっこよすぎて密かにキュンでした。
ナジャ
フロントエンド担当。 東京の凄さに圧倒されている賑やかし担当2号。
ひととり
PdM担当 と言いつつもUIもフロントもバックエンドも全部やる。皆ついてきてくれてありがとう!
Discussion