Version: 2019.1
카메라에서 일정 거리 떨어진 절두체의 크기
카메라에서 나오는 레이

돌리 줌(일명 “Trombone” 효과)

돌리 줌(Dolly Zoom)은 카메라를 타겟 오브젝트를 향해 움직임과 동시에 오브젝트에서 줌 아웃하는 잘 알려진 시각 효과입니다. 그 결과 오브젝트는 대략 같은 크기로 표시되지만 씬 내 다른 오브젝트는 모두 원근이 변경됩니다. 약하게 사용할 경우, 돌리 줌은 타겟 오브젝트를 하이라이트하는 효과가 있습니다. 이 오브젝트는 씬의 이미지에서 유일하게 포지션이 이동하지 않기 때문입니다. 대신 방향 감각을 잃은 듯한 인상을 주기 위해 줌을 의도적으로 빠르게 조정할 수 있습니다.

절두체에 세로로 딱 맞는 오브젝트는 카메라와 오브젝트의 거리나 시야각에 관계없이 화면에 보이는 뷰의 전체 높이를 차지합니다. 예를 들어 카메라를 오브젝트에 더 가까이 움직이면서 오브젝트가 절두체의 높이에 계속 딱 맞도록 시야각을 넓힐 수 있습니다. 이 특정 오브젝트는 거리와 시야각이 변해도 화면에 같은 크기로 표시되지만 다른 것은 거리나 FOV 등 크기가 변합니다. 이것이 돌리 줌 효과의 본질입니다.

코드에서 효과를 작성할 때는 줌을 시작할 때 오브젝트가 있는 포지션에서 절두체의 높이를 저장하는 것이 중요합니다. 그러면 카메라가 움직일 때 오브젝트의 새 거리를 구하고 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 스크립트 예

카메라에서 일정 거리 떨어진 절두체의 크기
카메라에서 나오는 레이