ロストビレッジ4つの秘宝

ついに75歳になってしまいました。パピコンPC6001で文字を書き音を鳴らして喜んでいたらインターネットの時代になり、ネットでほとんどの事が調べられるようになりました。そしてAIが誕生しました。こんな未来まで来れたのですからびっくりです。
そこで久しぶりにGeminiにおんぶにだっこでゲームをつくってみました。アイデアから、アセット探し、Unityのコード書きまで全てGeminiまかせです。やりたい事を伝えてコードを組んでもらい、試して動きがおかしければ何度も繰り返しやり直してもらいました。
PUN2を使った2Dアクションパズルゲームです。4つの宝箱を開けたら次の面です。

ゲーム説明
PC用:キーボードの カーソルキー「→」Numpad6[Keyboard]「←」Numpad4[Keyboard]で左右移動「↑」Numpad8[Keyboard]でジャンプです

<<Geminiとチャット>>>
[私]unity2Dの無料アセットで『ソーサリアン』のような雰囲気のものはありますか?
[Gemini]
『Pixel Art Village Props』と『Sunny Land』
[私]Pixel Adventure1で宝物を取って来るゲームを作ったことはあります。『Pixel Art Village Props』を使って雰囲気が異なるゲームができないかと考えています。なにかないでしょうか
[Gemini]
1. 「夜の静かな泥棒」アクション(ステルス・ミステリー)
2. 「村の何でも屋」アドベンチャー(クラフト・探索)
3. 「呪われた村」からの脱出(ホラー・パズル)
<<<とりとめのないチャットを続けてアイデアを練りました>>>
[私]『Village Props』ではTexture「TX Tileset Ground」をTileMapに、小道具になるTexture「TX Village Props」をプレハブにしています。「TX Village Props」もTileMapにしたいです。
[Gemini]
タイルマップとして綺麗に並べるには、以下の手順を試してみてください:Sprite Editorでの分割: 「Grid By Cell Size」を選択し、Pixel Sizeを 16 x 16 に設定してSliceしてみてください。
[私]groundのtilemapがすでにありますがグリッドが32×32です。どうやったら16×16のグリッドをつくれますか?
[Gemini]
新しいTilemapのインスペクターで、Tilemap Renderer ではなく Tilemap コンポーネントを見ます。その中の Tile Anchor はそのままに、Tilemap の Scale(Transformの方)を 0.5, 0.5, 1 に設定してください。なぜ「Scaleを0.5」にするのか?親のGrid (32×32): 1ユニット(1マス)の物理的な大きさは変わりません。子のTilemap (Scale 0.5): 内部的に「1マスの大きさが半分」になります。結果: 32×32の地面タイル1枚のスペースに、16×16の小道具タイルをきっちり**4枚(2×2)**並べられるようになります。これなら、地面の当たり判定(32px単位)と、小道具の細かい配置(16px単位)を同じ画面内で矛盾なく共存させられます。
「呪われた村」のパズルを作るなら、以下のように使い分けると非常に作りやすくなります。
レイヤー名   役割            設定のコツ
Ground    地面・壁(物理判定あり)  32×32のタイルで、しっかりした足場を作る。
Decoration  背景の草・模様       16×16のタイル。
Props (Prefab) 樽・箱・宝箱        TilemapではなくGameObjectとして配置。
<<<これはなかなかうまくいかず、かなりやり直しました>>>
[私]ステージ毎に宝箱を4つ設置してすべての宝箱を開けると次のステージに進めます。カスタムプロパティをセットにして、宝箱を4つ開けると次のステージの扉が開く仕様にしたいです
[Gemini]
「4つの宝箱をすべて開けたら扉が開く」という仕様は、マルチプレイヤーでの達成感を共有するのに最高のギミックですね。Web公開を想定しているため、**「誰がいつ参加しても、今の開閉状況が正しく反映されている」**必要があります。コードの修正案と、カスタムプロパティを使った管理方法を提案します。
1. カスタムプロパティの設計
// 宝箱進捗配列 (0番は不使用、1-10番に各ステージのカウントを入れる)
int[] chestProgress = new int[11];
hashTable.Add(“chestProgress”, chestProgress);
hashTable.Add(“currentMaxStage”, 1); // 先頭プレイヤーのいるステージ
2.Chest スクリプトで、最初に開けた人がプロパティを更新するようにします。インスペクターで「どのステージの宝箱か(1〜10)」を設定できるようにします。
Web公開での途中参加を考慮すると、「どのステージの宝箱か」をインスペクターで指定できるようにし、対応するカスタムプロパティ(stage1, stage2…)を更新する形がベストです。
3. ステージの扉(Door)の管理
各ステージの出口にある扉には、以下のスクリプトを付けて、自分のステージのカウントが「4」になるのを監視させます。
アドバイス:マルチプレイでの「途中参加」への配慮
宝箱を開けるRPCをAllBuffered:
RPC_Open を AllBuffered にしているため、ステージの途中で誰かが入室しても、既に開けられた宝箱は最初から「開いたアニメーション状態」で表示されます。
カウントの永続性:
カスタムプロパティに値を保存しているため、全員が一度退室しない限り、ステージの進行状況(宝箱を何個開けたか)はルーム内に保持されます。
<<<何度も要望を伝えなおして修正版の完成コードを作ってもらいました>>>
[私]BoxCollider2D,Rigidbody2D,PhotonView,PhotonTransformViewClassicを付けた箱をマスタークライアント以外が押したり転がしたりするとき重いです
[Gemini]
箱(Crate)をルームオブジェクトにして、プレーヤーと接触(OnTriggerStay2D)を調べてphotonView.TransferOwnership(PhotonNetwork.LocalPlayer)で所有権を移転するscriptを箱(Crate)に付けます。
<<<私から色々提案して何度もテストしてまとまりました>>>
[私]プレーヤーにPhoton Animator Viewを付けずにアニメーションの同期をとりたい
[Gemini]プレーヤーの位置と1つ前の位置から向きと移動スピードを取得して勝手にアニメーションするようにコードを修正します。
<<<このアイデアは私が出しました>>>
[私]『Pixel Art Village Props』に初めからある「PF Village Props – Elevator」と「PF Village Props – Bounding Platform」のscriptを最小の通信で同期させたい
[Gemini]
// — PUN2 決定論的同期ロジック — サーバー時刻を取得(オフライン時はTime.time)
double networkTime = PhotonNetwork.InRoom ? PhotonNetwork.Time : Time.time;
float cycleTimer = (float)(networkTime % totalCycleTime);
<<<この通信0で同期のアイデアにはびっくりです>>>
[私]playerがTilemapに押し込められてしまう事がある
[Gemini]
using UnityEngine.Tilemaps; //Tilemap操作用
// プレイヤーの中心点(足元より少し上が確実)の座標をタイル座標に変換
Vector3Int cellPos = floorTilemap.WorldToCell(transform.position + new Vector3(0, 0.2f, 0));
// その場所にタイルが存在するか(=埋まっているか)
if (floorTilemap.HasTile(cellPos))
<<<タイルマップのワールド座標取得です>>>
こんな事を繰り返している内にゲームになりました

コメント