[Unity3D] RPG게임 카메라 - 줌 인/아웃, 카메라 회전. [Part 4]

※ 주의 

이 글은 아마추어가 개인적으로 생각하여 작성하는 것으로, 이곳에 나오는 내용을 맹신하지 않는것을 당부드립니다.



기능정리


1. 플레이어를 따라오는 카메라.

1.5. 플레이어의 움직임.

2. 마우스 휠 카메라 줌 인,아웃 기능.

3. 마우스 오른쪽 버튼 클릭 후 카메라 회전.

- x,y축 회전

- x축 회전의 한계치 설정.




3. 마우스 오른쪽 버튼 클릭 후 카메라 회전.


Input에는 마우스의 움직임에 대한 정보도 제공해 주고 있다.


"Mouse X" 는 마우스의 좌,우 움직임을,

"Mouse Y" 는 마우스의 상,항의 움직임에 대한 정보를 가지고있다.


마우스 오른쪽 버튼을 누르고 있을 때 카메라의 회전이 가능하게 만들어보자.


벡터변수 Gap을 만들어서 Gap.x값에 Mouse Y값을 축적해보도록 하자.

'Gap.x인데 Mouse X값이 아니냐?' 라고 묻는다면, 아니라고 답변해주고 싶다.

Mouse Y는 상,하에 대한 움직임을 감지한다. 즉, 마우스 오른쪽 버튼을 클릭한 채

위로 올리면 카메라는 밑을 바라보게 되고, 밑으로 내리면 위를 바라보게 해야한다.

이러한 경우를 봤을 때 회전을 이용하는건데, y축 회전이 아닌 x축으로 회전을 가하기 때문에

Gap.x에 Mouse Y값을 축적할 필요가 있다.


※ x축으로 회전하기 때문에 Gap.x에 Mouse Y를 축적시킬 필요가 있다.


Gap.x에 Mouse Y의 양수 값으로 축적하게 된다면 마우스를 위로 올려야지 카메라가 위에서 밑을 바라보는 상황이 될것이다.

그렇기 때문에 -1을 곱해주어 음수값으로 만든다면 마우스 오른쪽 버튼 클릭 후 밑으로 드래그 한다면 카메라가 위에서 밑을 바라보는 상활을 만들수 있다.

 

※ 반대로 Gap.y에는 Mouse X를 축적해야한다.


이 카메라도 마찬가지로 회전의 최소값과 최대값을 Mathf.Clamp함수를 이용하여 지정할 수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class Axis : MonoBehaviour {
 
    public Quaternion TargetRotation;  // 최종적으로 축적된 Gap이 이 변수에 저장됨.
    public Transform CameraVector;
 
    public float RotationSpeed;        // 회전 스피드.
    public float ZoomSpeed;            // 줌 스피드.
    public float Distance;             // 카메라와의 거리.
 
    private Vector3 AxisVec;           // 축의 벡터.
    private Vector3 Gap;               // 회전 축적 값.
    
    private Transform MainCamera;      // 카메라 컴포넌트.
 
    void Start()
    {
        MainCamera = Camera.main.transform;
    }
 
    void Update()
    {
        Zoom();
        CameraRotation();
    }
 
    // 카메라 줌.
    void Zoom()
    {
        Distance += Input.GetAxis("Mouse ScrollWheel"* ZoomSpeed * -1;
        Distance = Mathf.Clamp(Distance, 5f, 20f);
 
        AxisVec = transform.forward * -1;
        AxisVec *= Distance;
        MainCamera.position = transform.position + AxisVec;
    }
 
    // 카메라 회전.
    void CameraRotation()
    {
        if (transform.rotation != TargetRotation)
            transform.rotation = Quaternion.Slerp(transform.rotation, TargetRotation, RotationSpeed * Time.deltaTime);
 
        if (Input.GetMouseButton(1))
        {
            // 값을 축적.
            Gap.x += Input.GetAxis("Mouse Y"* RotationSpeed * -1;
            Gap.y += Input.GetAxis("Mouse X"* RotationSpeed;
 
            // 카메라 회전범위 제한.
            Gap.x = Mathf.Clamp(Gap.x, -5f, 85f);
            // 회전 값을 변수에 저장.
            TargetRotation = Quaternion.Euler(Gap);
 
            // 카메라벡터 객체에 Axis객체의 x,z회전 값을 제외한 y값만을 넘긴다.
            Quaternion q = TargetRotation;
            q.x = q.z = 0;
            CameraVector.transform.rotation = q;
        }
    }
}
 
cs


Axis객체 인스펙터 정보.



Quternion.Euler(Gap);


오일러를 통해 축적된 Gap을 넣는다.

이 쿼터니언에는 얼만큼 회전하느냐에 대한 회전 값이 들어있다.

이러한 회전값을 TargetRotation에 초기화 시킨다.


그리고 transform.rotation(Axis객체 자신의 회전 값)에 저장된 회전값을 대입해줘도 되지만,

그렇게 되면 카메라가 서서히 회전하는 효과를 느낄수 없으므로, 쿼터니언의 슬러프 함수를 써서 목표회전을 사용하여

값을 대입 해준다.


Quternion.Slerp(현재 자신의 회전 값, 목표 회전 값,  회전 스피드);

정도로 보면 된다.



목표 회전을 하지 않았을 경우. (Slerp함수를 사용하지 않았을 경우.)

transform.rotation = TargetRotation;




목표회전을 사용한 경우. (Slerp함수를 사용한 경우.)

transform.rotation = Quaternion.Slerp(transform.rotation, TargetRotation, RotationSpeed * Time.deltaTime);



1
2
3
4
5
 
 Quaternion q = TargetRotation;
 q.x = q.z = 0;
 CameraVector.transform.rotation = q;
 
cs


새롭게 쿼터니언 변수q를 만들어서 TargetRotation을 대입한 이유는

TargetRotation값을 회손하면 안되기 때문이다. 

※ TargetRotation는 카메라를 x,y축을 회적시키는데 필요한 값이다.


쿼터니언변수 q에 x,z값을 0으로 초기화 시킨다.

y값만을 사용할 건데, 잘 생각해보면 현재 이 쿼터니언 값을 카메라의 회전값이다.

카메라의 x,z값을 0으로 초기화 시키고 y값만을 쓴다면 어떻게 될까?


바로 이렇게 된다.


x,z값을 0으로 고정시켰기 때문에 y축에대한 회전을 한다.

지금 회전하는 이 객체는 맨 처음에 만들어 두었던 CameraVector객체이다.


이 객체를 y회전만 시키는 이유는 카메라가 회전했을 때 카메라가 보는 방향에서 플레이어를 자유롭게 조종하기 위함이다.

플레이어는 이 객체(CameraVector)에 벡터값을 가져와서 이동한다.




완성.