돌리 줌(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 스크립트 예