1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Fov違いのカメラスタックも一緒にズームする

Last updated at Posted at 2025-12-12

はじめに

カメラスタックでfovが違うカメラを重ねている状況でズームしたい場合
単にカメラ移動で近づけるといったアプローチでは、同じ移動量に対する拡大率がカメラごとに変わってくるので、うまくズームができません
(カメラごとに移動量を補正すれば可能だが…面倒でしょう)

GIF 2025-12-12 2-56-52.gif
(カメラ1 赤キューブ Fov60、カメラ2 青キューブ Fov30)

また、ズーム中心が常に画面中央であれば、各カメラのFovに対して同じ比率を掛ける方法でも上手くいったりしそうですが
そうでない場合は、ちょっと面倒くさそうです。

この辺をいい感じにできないかなと考えていました。

投影行列を触ってしまえ

UnityではCameraコンポーネントから投影行列を取得して直接操作できるので
これをいじってしまうアプローチです

CameraZoom.cs
using UnityEngine;

public class CameraZoom : MonoBehaviour
{
    // BaseカメラとOverlayカメラを登録
    [SerializeField] private Camera[] _cameras = new Camera[0];
    [SerializeField] private float _zoom = 1.0f;
    
    void LateUpdate()
    {
        foreach (Camera cam in _cameras)
        {
            // 行列をリセット
            cam.ResetProjectionMatrix();
            Matrix4x4 proj = cam.projectionMatrix;
            
            // スケーリング XYのみ
            proj[0, 0] *= _zoom;
            proj[1, 1] *= _zoom;
            cam.projectionMatrix = proj;
        }
    }
}

各カメラの元の投影行列に対して、同じだけXY方向にスケーリングすることでズームしています

GIF 2025-12-12 2-57-57.gif

ズームの中心を変える

ズームの中心を変えたい場合も、同様に行列を弄れば良さそうです。

CameraZoom.cs
using UnityEngine;

public class CameraZoom : MonoBehaviour
{
    // BaseカメラとOverlayカメラを登録
    [SerializeField] private Camera[] _cameras = new Camera[0];
    [SerializeField] private float _zoom = 1.0f;
    
    // ズーム中心
    [SerializeField, Range(-1,1f)] private float _centerX = 0;
    [SerializeField, Range(-1,1f)] private float _centerY = 0;
    
    void LateUpdate()
    {
        foreach (Camera cam in _cameras)
        {
            // 行列をリセット
            cam.ResetProjectionMatrix();
            Matrix4x4 proj = cam.projectionMatrix;
            
            // スケーリング XYのみ
            proj[0, 0] *= _zoom;
            proj[1, 1] *= _zoom;

            // ズーム中心の移動
            proj[0, 2] += _centerX * (_zoom - 1f);
            proj[1, 2] +=  _centerY * (_zoom - 1f);
            
            cam.projectionMatrix = proj;
        }
    }
}

GIF 2025-12-12 3-36-05.gif

まとめ

  • Fovが違う複数のカメラを重ねていても、投影行列を直接弄ることで共通のパラメータで一緒にズームすることができた

小ネタにはなりましたが、ゲーム開発だとズーム演出を使う機会も多いと思うので
何かの役に立てば幸いです。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?