【Unity C# スクリプト】マウスドラッグ・ホイールでメインカメラ位置制御

マウス操作でメインカメラの位置を制御可能にし、好きな角度から好きな倍率でシーンを見ることができるようにしてみよう。
そのためには、まずメインカメラの位置を球座標系で表すことにする。

public class ScrCamera : MonoBehaviour {
    public Vector3 m_target;    //   ターゲット位置
    public float m_distance;    //  ターゲット位置からの距離
    public float m_latitude;    //  緯度(上から見下ろしている場合: > 0)、[-90, +90]
    public float m_longitude;   //  経度(Z軸+方向から見ている場合:== 0)、Y軸+方向からみて時計回り、[0, 380)
    .....
}

コードは上記のようになる。
メインカメラが中央に捉えるターゲットの位置と、そこからの距離、緯度・経度(球座標系)をメンバ変数として保持する。

上記のデータが更新された場合、updateCamera() が呼ばれ、メインカメラの位置・方向が設定される。

    //  カメラ位置、向きを設定
    void updateCamera()
    {
        float y = m_distance * Mathf.Sin(m_latitude * Mathf.Deg2Rad);
        float t = m_distance * Mathf.Cos(m_latitude * Mathf.Deg2Rad);
        float x = t * Mathf.Sin(m_longitude * Mathf.Deg2Rad);
        float z = t * Mathf.Cos(m_longitude * Mathf.Deg2Rad);
        Camera.main.transform.position = new Vector3(x, y, z) + m_target;
        Camera.main.transform.LookAt(m_target);
    }

Mathf.Deg2Rad は、デグリーをラジアンに変換するための定数だ。
カメラの位置は、球座標で計算した変位にターゲット座標を加え、メインカメラの transform.position に代入している。
カメラの向きは LookAt(目標位置) で設定している。

このように Unity スクリプトには必要な機能がちゃんと用意されており、便利だなーと感心させられる。

これで、準備が整ったので、Start() で以下のようにカメラ位置・向きを初期化しておく。

    void Start () {
        m_target = new Vector3(0, 0, 0);
        m_distance = 5;
        m_latitude = 30;
        m_longitude = 45;
        updateCamera();
    }

カメラ初期位置などは適当に決めている。

次に、カメラ位置の更新だが、まずは簡単なマウスホイールによる拡大縮小から。
ターゲットとカメラの距離(m_distance)を増加させると縮小、減少させると拡大になるので、ホイールの回転を検知したら、増加・減少させるようにする。

    void Update()
    {
        float mouseWheelScroll = Input.GetAxis("Mouse ScrollWheel");
        if (mouseWheelScroll != 0)
        {
        	m_distance -= mouseWheelScroll*4;
        	if( mouseWheelScroll < 0 )
        		m_distance *= 1.1f;
        	else
        		m_distance /= 1.1f;
            if ((m_distance -= mouseWheelScroll*4) < 1)
                m_distance = 1;
            else if (m_distance > 1000)
                m_distance = 1000;
            updateCamera();
        }
        ....
    }