あなたはとあるゲーム会社のプランナーです。
今どきのプランナーらしく、多少のUnity知識はあるようです。
あなたは相棒プログラマーの 反重力(そりしげ つとむ)さんとペアプロをしながら、
ディレクターに見せるための迷路ゲームのモックアップを作ることになっています。
お昼休みは終わっていますが、反重さんはまだ来ていないようです。
少し遠くまで食べに行っているのかもしれません。
あなたはモック用のsceneを新しく作成し、
壁やプレイヤーの簡単なprefabを作りながら彼が戻ってくるのを待ちました。
ーーー
反重さんが戻ってきました。(…カレー食べてきたな)
まずは、今あなたが作ったモック用のシーンをみせて、
彼が理解できているか確認するところから始めましょう。
(ここからリプレイ)
1. シーンの現状確認
あなた:
このフォルダはUnityプロジェクトです。3DMaze/Scenes/MazeScene.unity の現在の状況はわかりますか?
反重:
MazeScene.unity の現在の状況は以下の通りです。
シーンに含まれるオブジェクト:
- Main Camera: 位置 (0, 1, -10) に配置されたメインカメラ (URP設定済み)。
- Directional Light: シーン全体を照らすライト。
- Global Volume: ポストプロセス用のボリューム。
- Ground: 位置 (0, -0.25, 0)、スケール (64, 0.5, 64) の巨大な直方体(床)。
現状の分析:
- 迷路自体は存在しません: シーン内には迷路の壁や構造物は配置されていません。
-
ゲームロジックもありません:
GameManagerやMazeGeneratorのようなスクリプトがアタッチされたオブジェクトは見当たりません。 -
スクリプトファイル: プロジェクト全体を検索しましたが、ゲームロジックに関連するC#スクリプト (
.cs) は見つかりませんでした(TutorialInfoのReadme関連のみ)。
このシーンは、URPの基本的なセットアップに床を置いた初期状態、あるいは迷路生成の実装前の状態であると考えられます。
2. プレハブの調査
あなた:
3DMaze/Prefabs/WallPrefab.prefab これがどのようなものか確認してください
反重:
WallPrefab.prefab の内容は以下の通りです。
構造:
-
ルートオブジェクト (
WallPrefab):- コンポーネント:
Transformのみ。 - 役割: 親コンテナ。位置・回転の基準点となります。
- コンポーネント:
-
子オブジェクト (
WallObj):-
Transform:
- 位置: (0, 1, 0) -> 親の基準点からY軸方向に1上がった位置。
- スケール: (0.1, 2, 1) -> 薄くて背の高い形状(幅0.1、高さ2、奥行き1)。
- MeshFilter: Unity標準の Cube メッシュを使用。
-
MeshRenderer: マテリアル(GUID:
65ad0910ebc674148962911522d8992d)が割り当てられています。 - BoxCollider: サイズ (1, 1, 1) の当たり判定。
-
Transform:
分析:
これは迷路の「壁」の1単位として使われるプレハブです。
親オブジェクトのピボットが足元(Y=0)にあり、子オブジェクトの壁(高さ2)がその上に立つように配置されています(中心がY=1なので、Y=0からY=2までの高さになります)。
幅が0.1と薄く設定されているのが特徴です。
3. 迷路生成スクリプトの作成(初期案)
あなた:
それでは、この 3DMaze/Prefabs/WallPrefab.prefab を使用して迷路を作成するスクリプトを用意してください。迷路の幅および奥行は変数で用意し、それぞれ10から128までの可変として下さい。初期値はどちらも32です。
迷路は原点を中心として生成してください。
足りない条件があれば尋ねてください
反重:
迷路生成スクリプトの実装計画を作成しました。
確認事項:
- アルゴリズム: 一般的で質の高い「穴掘り法」を採用します。
- サイズ補正: 穴掘り法の特性上、サイズは奇数が望ましいため、偶数が指定された場合は内部で調整(+1など)して生成します。
-
壁の向き:
WallPrefabは薄い板状ですが、今回は「壁マス」として配置します。まずは回転なしで配置しますが、見た目が気になる場合は後で調整可能です。 - 床の調整: 迷路の大きさに合わせて床(Ground)のサイズも自動調整する機能を付けます。
この方針で進めてよろしいでしょうか?
あなた:
もちろんです。素晴らしいですね(承認)
反重:
MazeGenerator.cs を作成しました。
Unityエディタ上で以下の手順を行って、迷路生成を確認してください。
-
空のGameObjectを作成: 名前を
GameManagerなどにします。 -
スクリプトをアタッチ: 作成したオブジェクトに
MazeGeneratorスクリプトをアタッチします。 -
参照の割り当て:
-
Wall Prefab:Assets/3DMaze/Prefabs/WallPrefabをドラッグ&ドロップ。 -
Ground: シーン内のGroundオブジェクトをドラッグ&ドロップ。
-
- 実行: Playボタンを押すと、原点を中心に迷路が生成され、床のサイズも自動調整されるはずです。
-
サイズ変更: インスペクタで
Width/Depthを変更して、生成される迷路が変わることを確認してください。
4. 仕様変更:薄い壁とDFSへの変更
あなた:
スミマセン、指示が間違っていました…
壁はブロックではなく、板としてください。10x10のサイズであれば100か所の歩ける場所があります。また、板なので9x9など奇数サイズの迷路も作成できる必要があります。迷路の通路のつながる方向に合わせて、壁の向きも変更する必要があります。
反重:
迷路生成のロジックを「薄い壁(板)」を使用する方式に変更する計画を立てました。
変更点:
- アルゴリズム: 「穴掘り法」から**「壁伸ばし法」または「DFS(深さ優先探索)」**に変更します。これにより、マス目(セル)の間の壁を取り除く形で迷路を作ります。
- サイズ: 10x10なら正確に10x10のセル(歩ける場所)ができます。奇数・偶数問わず指定可能です。
-
壁の配置と回転:
- セルの「右」と「上」に壁があるかどうかを管理します。
- 縦の壁: そのまま配置(Z軸方向に伸びる)。
- 横の壁: 90度回転して配置(X軸方向に伸びる)。
- 外周の壁も生成します。
この計画で実装を進めます。よろしいでしょうか?
あなた:
お願いします!
反重:
MazeGenerator.cs を更新しました。
変更内容:
- アルゴリズム: DFS(深さ優先探索)に変更し、指定されたサイズ(例: 10x10)のセルを正確に生成します。
- 壁の生成: マス目の間に「薄い壁」を配置するように変更しました。
- 回転: 横方向の壁(Top/Bottom)には90度の回転を適用しています。
確認手順:
Unityエディタで再度Playモードを実行し、以下の点を確認してください。
- 迷路が「薄い壁」で構成されているか。
- 壁の向きが正しいか(隙間なくつながっているか)。
- 指定したサイズ(Width/Depth)通りのマス目ができているか。
5. 仕様変更:親子関係とスケーリング
あなた:
ありがとう。大筋はあっています。
迷路をGroundの子として設置するようにしてください。
また、Groundも含めた迷路の見た目のサイズを可変できるように、迷路のscaleの変数を用意してください。初期値は2としてください。
反重:
迷路をGroundの子オブジェクトにし、スケール可変にする計画を立てました。
実装方針:
-
階層構造:
Ground->MazeContainer->Wallsとします。 -
歪み防止:
Groundをリサイズ(非等倍スケール)すると、そのまま子にした壁が歪んでしまいます(特に回転時)。これを防ぐため、MazeContainerに 逆スケール を掛けて、実質的にワールド座標系と同じ状態に戻します。 -
スケール変数:
scale(初期値2) を導入し、これを「1マスの大きさ」として扱います。壁の長さや配置間隔がこの値に基づいて計算されます。
この方針で実装します。よろしいでしょうか?
あなた:
お願いします!(こればっかりや)
反重:
MazeGenerator.cs を更新しました。
変更内容:
-
親子関係: 迷路(
MazeContainer)がGroundの子オブジェクトとして生成されます。 -
スケール変数:
Scale(初期値 2.0) を追加しました。これを変更すると、迷路全体のサイズ(通路の幅など)が変わります。 -
歪み防止:
Groundのサイズ変更による壁の歪みを防ぐため、MazeContainerに逆スケールを適用しています。
確認手順:
UnityエディタでPlayモードを実行し、以下の点を確認してください。
- Hierarchyウィンドウで
Groundの下にMazeContainerがあり、その中にWallPrefabが生成されていること。 -
Groundのサイズが迷路に合わせて自動調整されていること。 - 壁が歪んでいないこと(特に回転している壁)。
- インスペクタで
Scaleを変更して、迷路の広さが変わること。
6. ログ保存
あなた:
問題ないようです。ありがとうございます。
ここまでのやり取りを、3DMaze/Documents にlog.mdとして保存してください。
反重:
ここまでの作業内容を Assets/3DMaze/Documents/log.md に保存しました。
他にお手伝いできることはありますか?
あなた:
log.mdは、こちらの質問/指示およびこれまで答えてもらった日本語の返事を時系列で記録してください。
「このフォルダはUnityプロジェクトです。@MazeScene.unity の現在の状況を教えてください」から始まり。このチャットも含めて記録してください。
反重:
了解です(本ファイルを作成)
7. Player操作の実装
あなた:
続いてplayerを操作するスクリプトを用意してください。
playerのモデルは 3DMaze/Prefabs/PlayerPrefab.prefab を使用し、迷路内の左下にInstantiateしてください。
移動にはInputSystemを使用し、方向キーの上下で前進と後退、左右で回転するものとします。
移動スピードの変数を用意し、デフォルト値は毎秒2mとしてください。
ログも引き続き追加していってください。
反重:
Player操作の実装計画を作成しました。
実装方針:
-
PlayerController.cs:
- Input System を使用して入力(矢印キー)を受け取ります。
- CharacterController を動的に追加して、壁との当たり判定を行いながら移動します。
- 移動速度はデフォルトで 2.0m/s です。
-
MazeGenerator.cs:
- 迷路生成後、左下(グリッド座標 0,0)にプレイヤーを生成します。
- PlayerPrefab への参照を追加します。
この方針で実装します。よろしいでしょうか?
あなた:
ばっちりです。お願いします!
反重:
PlayerController.cs を作成し、MazeGenerator.cs を更新しました。
実装詳細:
- PlayerController は RequireComponent(typeof(CharacterController)) を持ち、自動的にコンポーネントを取得します。
- MazeGenerator は PlayerPrefab を MazeContainer の子として生成し、CharacterController と PlayerController がアタッチされていない場合は動的に追加します。
- プレイヤーの初期位置は、迷路の左下(グリッド座標 0,0)に対応するワールド座標に設定されます。
確認手順:
- Unityエディタで GameManager (MazeGenerator) の Player Prefab 欄に Assets/3DMaze/Prefabs/PlayerPrefab を割り当ててください。
- Playモードを実行し、プレイヤーが迷路の左下に生成されることを確認してください。
- 矢印キー(上下左右)でプレイヤーが移動回転することを確認してください。
- 壁にぶつかって通り抜けられないことを確認してください。
あなた:
確認させてください。3DMaze/Prefabs/PlayerPrefab.prefab には 3DMaze/Scripts/PlayerController.cs をアタッチする必要はありませんか?
反重:
はい、必須ではありません。
MazeGenerator.cs の実装により、生成時に PlayerController コンポーネントがアタッチされていない場合は、自動的に AddComponent されるようになっています。
ただし、プレハブにあらかじめアタッチしておいても問題ありません。その場合は、インスペクタで速度などのパラメータを事前に調整できるというメリットがあります。
あなた:
了解です。それではあらかじめアタッチして確認します。
反重:
承知いたしました。
プレハブにアタッチすることで、インスペクタからパラメータ調整がしやすくなります。
動作確認よろしくお願いいたします。
あなた:
確認しました。PlayerはGroundのヒエラルキーの下ではなく、rootに生成してください。プレイヤーのサイズは迷路のスケールにかかわらず一定となります。
反重:
承知いたしました。
MazeGenerator.cs を修正し、プレイヤーをヒエラルキーのルートに生成するように変更しました。
これにより、迷路のスケール(Ground や MazeContainer のスケール)の影響を受けず、プレイヤーは常に一定のサイズ((1,1,1))で生成されます。
8. カメラ制御の実装
あなた:
続いてカメラを制御するスクリプトを用意してください。
カメラは一人称視点とし、プレイヤーの位置に置いてください。
プレイヤーがカメラの邪魔にならないよう、いったんプレイヤーを非表示にしてください。
反重:
カメラ制御用のスクリプト FPSCamera.cs を作成する計画を立てました。
実装方針:
-
FPSCamera.cs:
- Start() で Camera.main を取得し、プレイヤーの子オブジェクトにします。
- 位置を目の高さ(Y=1.5付近)に設定します。
- プレイヤーの MeshRenderer を全て無効化して非表示にします。
-
MazeGenerator.cs:
- プレイヤー生成時に FPSCamera コンポーネントを自動的に追加します。
この方針で実装します。よろしいでしょうか?
あなた:
お願いします!(承認)
反重:
FPSCamera.cs を作成し、MazeGenerator.cs を更新しました。
実装詳細:
- FPSCamera コンポーネントがプレイヤーに追加されると、メインカメラがプレイヤーの頭の位置(Y=1.5)に移動し、追従するようになります。
- プレイヤー自身のモデル(MeshRenderer)は非表示になります。
確認手順:
- UnityエディタでPlayモードを実行してください。
- 視点が一人称(プレイヤーの目の高さ)になり、プレイヤー自身が見えなくなっていることを確認してください。
- 移動回転に合わせてカメラも動くことを確認してください。
あなた:
動作を確認しました。本日はここまでにしましょう。お疲れ様でした!
反重:
お疲れ様でした!
本日は迷路生成、プレイヤー移動、FPSカメラの実装を行いました。
明日もよろしくお願いします。
(了)

