Unity勉強中!あこがれだったプログラマーに今からなろう!

昔あこがれだったプログラマー。今からでもUnityを勉強してみようと思い立ち、チャレンジ開始! Unity勉強メモや、悪戦苦闘な日々の記録です。

3D脱出ゲーム:Zoom機能を改造しよう。

今日はアイテムのZoom機能の改造です。

作成中のゲームはFPS視点で、ある程度は自由に歩き回れるようになりますが、
そうすると、今のZoom機能のままでは色々と問題が出てくる可能性があります。
今までの仕組みでは、下図のようにZoom用のCanvasを置いて、ここにZoom用のObjectを生成して、回転させたりしていました。

この方法では、カメラとZoom用のCanvasの間に、ある程度以上の空間をどうしても確保する必要があります。
どういう事かと言いますと、Zoom用のObjectは実際にCanvas上で回転することがあるため、カメラとCanvasが近すぎると、Objectがカメラの後ろ側にまで達してしまう可能性があります。
また、FPS視点でPlayerが動き回った場合、Canvasとカメラの間に、他の構造体が入ってきてしまう可能性もあります。
どちらの場合も、Zoom用のObjectが構造体の影に隠れたり、見え方がおかしくなったりと、ちょっと都合が悪い。
FPS視点でなければ、今の仕組みで十分なのですが、安易にFSP視点にしようとしたばっかりに、改造する必要が出てきたわけです😅

改造方法については、以前の3Dアクションゲームのミニマップを表示させた仕組みの応用でなんとかなりそうです。

amaniku.hatenablog.com

要は、Zoom用のObjectはCanvasとは別の位置で生成し、それを専用に撮影するカメラを作成して、その映像をRenderTextureで受け取って、Zoom用のCanvas上に設置したRaw Imageに表示させるわけです。

今までの仕組みでは、Zoom用Objectはドラッグすることで回転させる事ができました。
改造後はZoom用ObjectはCanvas上にはないので、直接ドラッグすることはできません。
代わりに、Canvasをドラッグした量に応じて回転させても良かったのですが、自動でゆっくり回転させ続けることにしました。
こうすれば、Zoom用ObjectにはColliderもEventTriggerも必要ないので、ちょっと楽になるかなあと言う思惑です😁

これでZoom用のCanvasは、思いっきりカメラに近づけても、Zoom用のObject問題なくなりました。

Zoom機能の呼び出しですが、今までの仕組みではSlotをクリックして選択状態にしてから、パネル上の虫眼鏡アイコンをクリックすることでZoom Canvasが表示されていました。
昨日の改造で開閉式のウィンドウ型になったItemBoxで同じようにしても良かったのですが、
ゲームシステムの設計で、ノーマルモードとサーチモードを分けてみようと思っていたこともあり、虫眼鏡アイコンは、モード切り替えに使おうと思っていたので、こちらも仕組みを改造することにしました。

まず、虫眼鏡アイコンをクリックすることでサーチモードに切り替えます。
これはGameManagerにenumでGameModeを作成しておき、これを切り替えることで行います。
そして、サーチモードだとわかりやすい様に、マウスポインタを虫眼鏡型に変更することにしました。
マウスポインタの変更はとても簡単に実装できます。

Cursor.SetCursor(cursorTexture, Vector2.zero, CursorMode.Auto);

なんと、たったこれだけです。
cusorTextureにカーソルに指定したいSprite画像を指定すればOKです。
カーソルを戻す時は、このcusorTextureにnullを入れるだけです。

これでサーチモードの演出はできたので、この状態でItemBoxのSlotをクリックすれば、Zoom用CanvasにZoom用Objectを表示するようにします。

まず、Slot.csのClickSlotメソッドにZoom Canvasを制御するZoomPanel.csに自身が格納しているitemを引数として渡します。

class Slot
    public void ClickSlot()
    {
        if(GameManager.instance.gameMode==GameMode.Type.Search)//Game Modeの確認
        {
            if(item == null)//Slotにアイテムがあるか確認
            {
                return;
            }
            zoomPanel.ShowPanel(item);//zoomPnaelクラスのShowPanelにitemを引数で渡す
        }
    }


ShowPanelは渡されたItemからZoom用Objectを生成して、Zoom用Canvasに映し出されている舞台であるzoomObjStageの子として設定します。

class ZoomPanel
    public void ShowPanel(Item item)
    {
        Destroy(zoomObj);
        panel.SetActive(true);//Zoom用の舞台の表示

        GameObject zoomObjPrefab = ItemGenerator.instance.GetZoomItem(item.type);
        zoomObj=Instantiate(zoomObjPrefab, zoomObjStage);
        ItemComment.text=item.ItemComment;//itemの説明表示
        ItemName.text=item.ItemName;//itemの名前表示
        
        cts = new CancellationTokenSource();
        
        token=cts.Token;

        RotateObj(token).Forget();
             
    }

    private async UniTaskVoid RotateObj(CancellationToken token)
    {
        while(true)
        {
            // ここでオブジェクトを回転させる
            zoomObjStage.transform.Rotate(0, 30 * Time.deltaTime, 0);
            
            // 次のフレームまで待機
            await UniTask.Yield(token);
        }
    }

これでZoom機能の改造も終わり。
youtu.be

次は、いよいよゲームのメインになるイベントのシステムを作り込んでいくことにしよう。