Unityのカメラ画角は垂直画角
はじめに
Unityが提供するカメラコンポーネントは、画角(Field Of View)を垂直画角として計算します。そのため、アスペクト比を変えると、垂直方向の視界はそのままで、水平方向の視界だけが変化します。
本記事ではエディタ上でアスペクト比を変えた時に、カメラが映す画面がどう変化するかの実例をまとめました。
加えて、Unityのカメラ画角を水平画角に変えるスクリプトも紹介します。
Unityのカメラ画角
Unity標準のカメラの画角は、垂直画角として計算されます。
垂直画角は図示すると以下の画像の通りで、レンズから見える範囲の上下の両端を結んで出来る角度のことです。
インスペクタ上では、カメラの画角を「Field Of View」で操作できます。
一見「Field Of View Axis」をHorizontalに変更すれば、水平画角に変更できそうです。しかし、「Field Of View Axis」をHorizontalに指定した時の「Field Of View」の値は、「現在の垂直画角」と「現在のアスペクト比」から算出される水平画角であり、内部で持っている値は垂直画角のままです。
事実 UnityEngine.Camera.fieldOfView
の値は、常に垂直画角が入っています。
実際に画角と画面のアスペクト比をいじってみます。
検証のために、簡単なグリッドシェーダを用意しました。このグリッドシェーダを巨大なQuadに適用して、カメラに映しています。
垂直画角を60度に固定したままアスペクト比を変えるとどうなるかみてみます。
アスペクト比 16:9
アスペクト比 4:3
見比べると、縦の視界は変化せず、横の視界だけが変化しています。
このことから、垂直画角を基準にして、画面のアスペクト比から水平方向の視界を決定していることがわかりました。
(Free Aspectモードでアスペクト比を変化させると、横の視界だけが変化するのがよくわかります)
Unityのカメラを水平画角固定に変える
垂直画角と画面のアスペクト比が与えられた時、水平画角は以下の式で求められます。
この式を利用すれば、Unityのカメラにおいて水平画角を固定することが可能です。
以下のスクリプトで作られるコンポーネントをCameraオブジェクトにアタッチすれば、水平画角を固定できます!
[ExecuteInEditMode]
public class CameraAspectController : MonoBehaviour
{
private Camera cam;
[SerializeField] private float fieldOfViewDegree;
private enum FOVMode
{
Vertical,
Horizontal
};
[SerializeField] private FOVMode fovMode;
private void Awake()
{
cam = GetComponent<Camera>();
}
private void FixedUpdate()
{
float currentAspectRatio = cam.aspect;
float verticalFov = 0;
switch (fovMode)
{
case FOVMode.Vertical: // this.fieldOfViewDegreeが垂直画角
verticalFov = fieldOfViewDegree;
break;
case FOVMode.Horizontal: // this.fieldOfViewDegreeが水平画角
verticalFov = HorizontalToVerticalFov(fieldOfViewDegree, currentAspectRatio);
break;
}
cam.fieldOfView = verticalFov;
}
private float HorizontalToVerticalFov(float horizontalFov, float aspectRatio)
{
return 2f * Mathf.Rad2Deg * Mathf.Atan(Mathf.Tan(horizontalFov * 0.5f * Mathf.Deg2Rad) / aspectRatio);
}
private float VerticalToHorizontalFov(float verticalFov, float aspectRatio)
{
return 2f * Mathf.Rad2Deg * Mathf.Atan(Mathf.Tan(verticalFov * 0.5f * Mathf.Deg2Rad) * aspectRatio);
}
}
確かにアスペクト比にかかわらず横の視界を固定することができました。
Discussion