見出し画像

【Unity】カメラアングルを効率よく記録する方法


自分は過去3作脱出ゲームを作成し、現在4作目を作成中です。

ほぼ完成してます。

今までの脱出ゲームの作り方の問題点

私の脱出ゲームは「3Dモデルを撮影した画像」を使った2D脱出ゲームです。詳細は以下のnoteをご覧ください。

今までの自分で作成したPrefab上に3Dモデルを置いていく方法だとカメラのX座標を4ずらすごとに、別の地点に切り替わるので「この画像に映っちゃいけないモノが写ってるな…」と思っても、画像の再撮影がすぐにできました。

ランプの数=移動できる地点の数

しかし、今回は以下の3Dモデル上に、オブジェクトの3Dモデルを設置し、撮影していますので、今までの方法は使用できません。

※プリメロ工房さんは無料で使用できる高品質な3Dモデルを多数配布されています!

そこで、任意のカメラ座標を記録できるスクリプトを作成しました!
※このスクリプトを使用するには「Odin Inspector and Serializer」が必要です。

「CameraTransformRecorder」でできること

このスクリプトでできることは以下の通りです。

  1. 記録ボタンをクリックすることで、現在のカメラ座標を記録することができます。記録ボタンをクリックするごとに、座標1、座標2…と記録をされていきます。

  2. >>ボタンを押すと次の座標に、<<ボタンを押すと前の座標にカメラの座標が移動します。

  3. 座標番号を入力して、選択した記録地点に移動ボタンをクリックすることでもカメラ座標が移動します。

  4. 記録された座標には名前を付けることができます(「入口」、「宝箱1」など)。

「CameraTransformRecorder」の使い方

1.右クリックメニューから「作成」→「ScriptableObject」→「CaneraTransformData」を作成します。

2.カメラに「Camera Transform Recorder」をアタッチし、Camera Transform Dataは、先ほど作ったScriptableObjectを指定します。

3.記録ボタンを押すと、カメラの座標を記録することができます。

【注意】
Unityを再起動したときはCamera Transform DataがMissingとなっていますが、一度再生すると直ります。

「CameraTransformRecorder」のスクリプト

using UnityEngine;
using Sirenix.OdinInspector;
using System.Collections.Generic;

[CreateAssetMenu(fileName = "CameraTransformData", menuName = "ScriptableObjects/CameraTransformData", order = 1)]
public class CameraTransformData : ScriptableObject
{
    [ListDrawerSettings(Expanded = true, ShowIndexLabels = true)]
    public List<CameraTransformRecorder.RecordedTransform> recordedTransforms = new List<CameraTransformRecorder.RecordedTransform>();
}

public class CameraTransformRecorder : MonoBehaviour
{
    [System.Serializable]
    public class RecordedTransform
    {
        public string name;
        public Vector3 position;
        public Quaternion rotation;

        public RecordedTransform(string name, Transform transform)
        {
            this.name = name;
            this.position = transform.position;
            this.rotation = transform.rotation;
        }

        public void ApplyTransform(Transform target)
        {
            target.position = position;
            target.rotation = rotation;
        }
    }

    [Title("Camera Transform Data")]
    [InlineEditor(InlineEditorModes.FullEditor)]
    [SerializeField]
    private CameraTransformData cameraTransformData;

    private int indexCounter = 0;
    [ShowInInspector]
    [SerializeField]
    private int selectedIndex = 0;

    [Button("記録")]
    public void RecordCurrentTransform()
    {
        if (cameraTransformData == null)
        {
            Debug.LogWarning("CameraTransformDataが設定されていません。ScriptableObjectをアタッチしてください。");
            return;
        }
        
        string defaultName = "地点" + indexCounter.ToString("00");
        RecordedTransform newRecord = new RecordedTransform(defaultName, transform);
        cameraTransformData.recordedTransforms.Add(newRecord);
        indexCounter++;
    }

    [Button("選択した記録地点に移動")]
    public void MoveToSelectedTransform()
    {
        if (cameraTransformData == null || cameraTransformData.recordedTransforms.Count == 0) return;
        
        if (selectedIndex >= 0 && selectedIndex < cameraTransformData.recordedTransforms.Count)
        {
            cameraTransformData.recordedTransforms[selectedIndex].ApplyTransform(transform);
        }
    }

    [ShowInInspector]
    [HorizontalGroup("IndexControl")]
    [Button("<< 前へ")]
    public void DecreaseIndex()
    {
        if (cameraTransformData == null) return;

        if (selectedIndex > 0)
        {
            selectedIndex--;
            MoveToSelectedTransform();
        }
    }

    [ShowInInspector]
    [HorizontalGroup("IndexControl")]
    [Button("次へ >>")]
    public void IncreaseIndex()
    {
        if (cameraTransformData == null) return;

        if (selectedIndex < cameraTransformData.recordedTransforms.Count - 1)
        {
            selectedIndex++;
            MoveToSelectedTransform();
        }
    }

    [ShowInInspector]
    [HorizontalGroup("IndexControl")]
    [PropertyRange(0, "@cameraTransformData.recordedTransforms.Count - 1")]
    public int SelectedIndex
    {
        get => selectedIndex;
        set => selectedIndex = value;
    }
}

いいなと思ったら応援しよう!