본문 바로가기

Unity3D/Camera Switching

Unity 3D Camera Switching example

유니티 3D 게임에서 카메라 전환(Camera Switching) 예제


유니티에서는 한 장면에 무제한의 카메라를 설정할 수 있으며 스크립트를 이용하여 특정 카메라를 활성화/비활성화할 수 있다.

예를 들어, 산을 가운데 두고 일주도로가 있고 그 도로를 따라 자동차가 이동할 때 도로 주변에 다수개의 카메라를 설치하고 자동차가 지나갈 때마다 그 부근에 설치된 카메라가 영상을 보여준다면 일주도록 전체의 영역에 걸쳐서 자동차가 이동하는 영상을 볼 수 있을 것이다. 특정 카메라가 작동할 때는 그 전에 사용된 카메라는 작동을 멈추도록 비활성화하는 방법을 사용하는 것이다.


위의 예를 구현할 때 필요한 요령(?)을 나열해본다


카메라 활성/비활성 : camera.enabled = true/false


자동차가 특정 지점을 통과할 때 특정 카메라  ON/OFF

길을 가로질러서  Cube 오브젝트로 막아두고 Cube의 속성 중에서 IsTrigger 를 true 로 설정한다. 이 때  Cube 의 Mesh Renderer 콤포넌트를 체크해제하여 Cube 가 보이지 않고 자동차가 통과할 때 OnTriggerEnter() 함수가 호출되도록 한다. 즉, 보이지 않는 Cube가 센서 역할을 하도록 한다


도로의 특정 지점을 통과할 때 진출/진입 판단

Cube 2개를 가까이 설치하여 두번째 Cube를 통과할 때 먼저 통과한 Cube의 이름을 알면 자동차가 통과하는 방향을 알 수 있다


if( currPass==1 && prevPass==2 ) {

    // 1 지점에서 2 지점 방향으로 이동하는 것으로 판단됨

}


다수개의 Cube 에서 탐지되는 통과정보를 종합, 판단하여 특정 카메라를 ON/OFF 하는 스크립트

이런 내용의 스크립트는 어떤 특정 오브젝트에 포함시키기가 적절치 않으므로 빈 게임오브젝트를 하나 생성하고 그 곳에 스크립트를 포함시키면 된다


static 함수를 선언하고 외부의 게임 오브젝트에 포함된 스크립트에서 해당 static 함수를 호출하는 방법

예를 들어, CameraSwitcher.js 라는 스크립트에 setCurrPass() 라는 함수를 선언할 때 static 키워드를 사용한 후, 이 스크립트를 빈 게임오브젝트에 포함하도록 했다면 다른 게임오브젝트에서는 CameraSwitcher.setCurrPass() 와 같은 방법으로 호출할 수있다



아래에서 사용된 Wrangler Jeep 의 모델은 Sketchup Warehouse에서 다운로드할 수 있다.

https://3dwarehouse.sketchup.com/model.html?id=d85204bf30dcd714357d8d23f70c8906

JeepWrangler mod88.zip


장면 구성




위의 구성에서 산의 반대편에 2대의 카메라를 설치하여 자동차의 현재 위치가 어디든지 해당영역 카메라의 영상이 게임뷰의 우상단에 출력되도록 했다. 그러므로 화면의 동일한 위치에 2개의 카메라 영상이 출력되어야 하므로 자동차의 현재 위치에 따라서 해당 영역의 카메라가 활성화될 때 반대편의 카메라는 비활성화 되어야 할 필요가 있다. 위의 그림에서 Scene 뷰에 각 2개 카메라의 영상이 보이는데 서로 다른 방향에서 도로를 바라보고 있다.



카메라 설정

스크립트에서 카메라 객체를 구할 때 Tag 를 이용하면 빠르고 편하므로 2개의 카메라에 Tag를 지정한다(camera2, camera3)

또 게임뷰의 우상단의 작은 영역에 카메라의 영상이 출력되도록 아래 그림과 같이 설정한다





Cube가 통과 센서로 사용되도록 설정


Cube 1에서 Cube2로 이동한다면 Camera 2가 활성화되어 그 영상이 게임뷰의 우상단에 보여야 하고 Cube3에서 Cube4로 이동하는 것이 확인되면 Camera3이 활성화되어야 한다. Hierarchy 뷰에서 Cube의 이름은 각각 pass1, pass2, pass3, pass4 로 하였다


Cube가 자동차의 통과를 탐지하기 위한 센서로 사용되기 위해 4개의 Cube 를 다음과 같이 설정한다

Cube 보이지 않아야 하되 자동차가 통과할 때 OnTriggerEnter() 함수가 호출되어야 한다




Cube 에 다음과 같은 스크립트를 포함하도록 한다 (pass1, pass2, pass3, pass4에 아래의 코드를 동일하게 포함시킨다)

#pragma strict


function OnTriggerEnter (other : Collider) {


if(other.transform.name=="First Person Controller"){

var currPass:String = this.transform.name;

if(currPass=="pass1"){

CameraSwitcher.setCurrPass(1);

}else if(currPass=="pass2"){

CameraSwitcher.setCurrPass(2);

}else if(currPass=="pass3"){

CameraSwitcher.setCurrPass(3);

}else if(currPass=="pass4"){

CameraSwitcher.setCurrPass(4);

}

}

}



위의 스크립트에서 사용된 CameraSwitcher 클래스는 CameraSwitcher.js 파일에 다음과 같은 코드를 작성하여 빈 게임오브젝트에 포함시키면 된다

아래와 같이 static 함수를 선언하면 다른 오브젝트의 스크립트에서 CameraSwitcher.setCurrPass()와 같이 호출할 수 있다

CameraSwitcher.js

#pragma strict


private static var prevPass:int;

private static var currPass:int;


static var cam2:Camera;

static var cam3:Camera;



function Start() {

//print("Cam Switcher Start");

cam2 = GameObject.FindWithTag("camera2").camera; // 위에서 설정한 Tag를 이용하여 카메라 객체를 구함

cam3 = GameObject.FindWithTag("camera3").camera;

if(cam2==null || cam3==null) {

print("Can't find Cameras");

}

}


static function setCurrPass(passNo:int) {

prevPass = currPass;

currPass = passNo;

switchCamera();

}


static function switchCamera() {

if(prevPass==1 && currPass==2) { // pass1 -> pass2 방향으로 이동하면 Camera 2 가 작동

cam2.enabled = true;

cam3.enabled = false;

print("Camera 2 ON");

}else if(prevPass==3 && currPass==4) { // pass3 -> pass4 방향으로 이동하면 Camera 3 이 작동

cam2.enabled = false;

cam3.enabled = true;

print("Camera 3 ON");

}

}



FPC(First Person Controller)의 이동속도를 조절(느리게, 빠르게)할 수 있도록 다음과 같은 스크립트를 작성하여 First Person Controller에 포함시킨다

Shift + W 키를 누르면 속도가 빨라지고 그냥 W 키를 누르면 천천히 이동한다

#pragma strict


var walkSpeed: float = 7; // regular speed

var crchSpeed: float = 3; // crouching speed

var runSpeed: float = 20; // run speed

 

private var chMotor: CharacterMotor;

private var ch: CharacterController;

private var tr: Transform;

private var height: float; // initial height

 

function Start(){

    chMotor = GetComponent(CharacterMotor);

    tr = transform;

    ch = GetComponent(CharacterController);

height = ch.height;

}

 

function Update(){

 

    var h = height;

    var speed = walkSpeed;

    

    if (ch.isGrounded && Input.GetKey("left shift") || Input.GetKey("right shift")){

        speed = runSpeed;

    }

    if (Input.GetKey("c")){ // press C to crouch

        h = 0.5 * height;

        speed = crchSpeed; // slow down when crouching

    }

    chMotor.movement.maxForwardSpeed = speed; // set max speed

    var lastHeight = ch.height; // crouch/stand up smoothly 

    ch.height = Mathf.Lerp(ch.height, h, 5*Time.deltaTime);

    tr.position.y += (ch.height-lastHeight)/2; // fix vertical position

}



실행모드로 테스트할 때 자동차가 도로를 이동함에 따라서 게임뷰의 우상단 영상이 카메라2, 3의 영상으로 번갈아 가면서 변경되는 것을 확인한다


Camera 2 작동시의 영상




Camera 3 작동시의 영상


위의 2개의 그림에서 우상단 영상을 비교해보면 배경이 서로 달라진 것을 확인할 수 있다