カメラからの距離で求める錐台のサイズ
カメラからの Ray

ドリーズーム(別名 “トロンボーン” エフェクト)

ドリーズームは良く知られた視覚エフェクトで、カメラがターゲットオブジェクトに向かうと同時にズームアウトするものです。その結果、ターゲットオブジェクトはほとんど同じ大きさで表示されたまま、シーンの他のすべてのオブジェクトのパースペクティブが変化します。ドリーズームでは、イメージの中で唯一ターゲットオブジェクトの位置だけが移動しないため、さりげなく行うと、ターゲットオブジェクトをハイライトする効果があります。別の効果としては、ズームを意図的に素早く行う事で、方向感覚を失った印象を作り出すことができます。

Frustum の中に縦方向にちょうど収まるオブジェクトは画面で見たとおりにビューの高さ全体を占めます。これはオブジェクトのカメラからの距離がいくつであっても、Field of View が何であっても変わりません。例えば、カメラをオブジェクトに近づけて、Field of View を広げてオブジェクトがFrustum の高さにちょうどおさまるようにすることができます。その特定のオブジェクトは画面上で同じ大きさで表示されますが、その他のすべては、距離および Field of View の変さらに伴ってサイズが変更されます。これはドリーズーム効果の最重要点です。

コードでこのエフェクトを作成するには、ズーム開始時のオブジェクトの位置における錐台の高さを保存することになります。次に、カメラが移動するにつれ、新しい距離が見つかり、そしてオブジェクトの位置と同じ高さであるように FOV は保持されます。これは次のようなコードにより実現できます:

using UnityEngine;
using System.Collections;

public class ExampleScript : MonoBehaviour {
    public Transform target;
    public Camera camera;
    
    private float initHeightAtDist;
    private bool dzEnabled;

    // Calculate the frustum height at a given distance from the camera.
    void FrustumHeightAtDistance(float distance) {
        return 2.0f * distance * Mathf.Tan(camera.fieldOfView * 0.5f * Mathf.Deg2Rad);
    }

    // Calculate the FOV needed to get a given frustum height at a given distance.
    void FOVForHeightAndDistance(float height, float distance) {
        return 2.0f * Mathf.Atan(height * 0.5f / distance) * Mathf.Rad2Deg;
    }

    // Start the dolly zoom effect.
    void StartDZ() {
        var distance = Vector3.Distance(transform.position, target.position);
        initHeightAtDist = FrustumHeightAtDistance(distance);
        dzEnabled = true;
    }
    
    // Turn dolly zoom off.
    void StopDZ() {
        dzEnabled = false;
    }
    
    void Start() {
        StartDZ();
    }

    void Update () {
        if (dzEnabled) {
            // Measure the new distance and readjust the FOV accordingly.
            var currDistance = Vector3.Distance(transform.position, target.position);
            camera.fieldOfView = FOVForHeightAndDistance(initHeightAtDist, currDistance);
        }
        
        // Simple control to allow the camera to be moved in and out using the up/down arrows.
        transform.Translate(Input.GetAxis("Vertical") * Vector3.forward * Time.deltaTime * 5f);
    }
}

C# スクリプトの例

var target: Transform;

private var initHeightAtDist: float;
private var dzEnabled: boolean;


// Calculate the frustum height at a given distance from the camera.
function FrustumHeightAtDistance(distance: float) {
    return 2.0 * distance * Mathf.Tan(camera.fieldOfView * 0.5 * Mathf.Deg2Rad);
}


// Calculate the FOV needed to get a given frustum height at a given distance.
function FOVForHeightAndDistance(height: float, distance: float) {
    return 2 * Mathf.Atan(height * 0.5 / distance) * Mathf.Rad2Deg;
}


// Start the dolly zoom effect.
function StartDZ() {
    var distance = Vector3.Distance(transform.position, target.position);
    initHeightAtDist = FrustumHeightAtDistance(distance);
    dzEnabled = true;
}


// Turn dolly zoom off.
function StopDZ() {
    dzEnabled = false;
}


function Start() {
    StartDZ();
}


function Update () {
    if (dzEnabled) {
        // Measure the new distance and readjust the FOV accordingly.
        var currDistance = Vector3.Distance(transform.position, target.position);
        camera.fieldOfView = FOVForHeightAndDistance(initHeightAtDist, currDistance);
    }
    
    // Simple control to allow the camera to be moved in and out using the up/down arrows.
    transform.Translate(Input.GetAxis("Vertical") * Vector3.forward * Time.deltaTime * 5);
}

JS スクリプトの例

カメラからの距離で求める錐台のサイズ
カメラからの Ray