저번 편에 이어서 바로 시작하겠습니다!

 

한 가지 고쳐주고 싶은 게 있습니다! 바로 카메라에요! 왔다 갔다 할 때 슝 슝 이동하는 느낌이라 별로 좋지는 않습니다!

이것을 해결해주기 위해서 다시 GameSceneManager.cs로 갑니다!

 

카메라가 캐릭터를 따라다니게 해놨고, 씬 전환이 일어나면서 캐릭터의 위치벡터값이 바뀌니까 카메라가 급하게 슉 하고 따라붙는 현상이라서 그런 건데요!

GameSceneManager.cs

 

카메라를 캐릭터의 위치가 변경될 때 같이 변경해 주겠습니다!

 

이렇게 하면

Game

 

엄청 자연스럽게 바뀌었습니다! 이제 좀 일반적인 게임의 씬 전환 같죠?!?!? 뿌듯합니다!

 

그리고 이번엔 카메라의 영역을 좀 제한해 보겠습니다! 지금 현재는 카메라가 캐릭터를 어디가 됐던 무조건 가운데에 초점을 맞추고 따라다닙니다! 근데 맵이 무한정 클 수는 없으니, 원하는 영역의 끝에서는 카메라가 더 이상 이동하지 않도록 설정하는 작업이 필요합니다! 버츄얼 카메라를 이용해서 구현을 해볼게요!

 

먼저 씨네마신 버츄얼 카메라에서 CinemachineConfiner를 추가해 줍니다!

 

Cinemachine Confiner란?

더보기

Cinemachine Confiner는 Unity의 Cinemachine 카메라 시스템에서 사용되는 카메라의 이동 영역을 제한하는 기능입니다. 즉, 카메라가 특정 영역을 벗어나지 않도록 제한하는 역할을 합니다. 주로 2D 또는 3D 게임에서 카메라가 지정된 영역을 벗어나지 않도록 설정할 때 사용됩니다.

주요 목적:

Cinemachine Confiner는 카메라가 이동할 수 있는 경계를 설정하여, 카메라가 플레이어 또는 중요한 게임 객체의 시야를 벗어나지 않도록 제한합니다. 이를 통해 게임에서 카메라의 불필요한 이동이나 게임플레이 중 시각적 혼란을 방지할 수 있습니다.

사용 사례:

  • 2D 게임에서는 카메라가 특정 화면 범위 밖으로 나가지 않도록 제한하여, 플레이어가 중요한 오브젝트나 환경을 항상 볼 수 있도록 합니다.
  • 3D 게임에서는 카메라가 특정 영역을 벗어나지 않도록 하여, 플레이어가 항상 중요한 시점에서 게임을 진행할 수 있도록 합니다.

Cinemachine Confiner의 작동 원리:

Cinemachine Confiner는 주로 Collider나 Bounding Box와 결합하여 카메라가 특정 범위를 벗어나지 않도록 제한하는 기능을 수행합니다. Confiner는 Collider 컴포넌트와 함께 작동하며, 이 Collider는 카메라가 이탈할 수 없는 영역을 정의합니다.

주요 특징:

  1. 2D 및 3D 지원: Cinemachine Confiner는 2D 게임과 3D 게임 모두에서 사용될 수 있습니다. 2D 게임에서는 주로 BoxCollider2D를 사용하고, 3D 게임에서는 BoxCollider 또는 SphereCollider 등을 사용할 수 있습니다.
  2. 카메라 이동 제한: 카메라는 설정된 영역을 벗어나지 않도록 제한되며, 벗어나려 할 경우 자동으로 영역 내로 끌어당겨집니다.
  3. 매끄러운 전환: 카메라가 영역을 벗어나지 않도록 강제로 이동시키기 때문에, 게임 환경을 보다 자연스럽고 매끄럽게 관리할 수 있습니다.

사용 방법:

  1. Cinemachine Virtual Camera 추가: 카메라에 Cinemachine Virtual Camera를 추가합니다.
  2. Cinemachine Confiner 컴포넌트 추가: Cinemachine Virtual Camera 객체에 CinemachineConfiner를 추가합니다.
  3. Collider 설정: Confiner의 영역을 정의하기 위해 Collider 컴포넌트를 사용합니다. 예를 들어, **2D 게임에서는 BoxCollider2D**를 사용하고, **3D 게임에서는 BoxCollider**를 사용할 수 있습니다.
  4. Confiner 설정: Cinemachine Confiner의 Bounding Volume 항목에 Collider를 지정합니다. 이 Collider는 카메라가 벗어나지 않도록 제한할 영역입니다.

Confiner 속성:

  • Bounding Volume: 카메라가 이동할 수 있는 경계를 정의하는 Collider입니다. 이 Collider 영역 내에서만 카메라가 이동할 수 있습니다.
  • Damping: 카메라가 Confiner의 경계를 벗어날 때, 얼마나 부드럽게 이동할지에 대한 속도입니다. 이 값이 클수록 카메라는 경계를 벗어나지 않으려고 더 빠르게 이동합니다.
  • Confine Screen Edges: 활성화하면, 카메라가 지정된 Bounding Volume을 벗어나지 않도록 하며, 이때 경계에 가까운 화면 가장자리를 제한합니다.

예시: 2D 게임에서 Cinemachine Confiner 사용하기

  1. Cinemachine Virtual Camera를 게임 객체에 추가합니다.
  2. BoxCollider2D를 사용하여 게임 영역을 정의합니다.
  3. Cinemachine Confiner 컴포넌트를 Cinemachine Virtual Camera에 추가하고, Bounding Volume으로 BoxCollider2D를 설정합니다.
  4. 필요한 경우 Damping 값을 조정하여 카메라가 경계를 벗어날 때의 반응 속도를 조절할 수 있습니다.

 

요약:

Cinemachine Confiner는 카메라가 지정된 경계를 벗어나지 않도록 제한하는 기능을 제공하며, 게임에서 불필요한 카메라 이동을 방지하고, 플레이어가 중요한 요소들을 항상 볼 수 있도록 하는 데 사용됩니다. Collider를 이용해 경계를 설정하고, Cinemachine Confiner에서 해당 경계를 지정하여 카메라가 그 영역을 벗어나지 않도록 합니다.

이 기능을 활용하면 카메라 이동이 자연스러우면서도 플레이어가 게임 환경에 맞는 시점을 유지할 수 있도록 도와줍니다.

 

CinemachineConfiner 주요 구성 요소

1. m_BoundingShape2D

  • 타입: Collider2D
  • 설명: 이 변수는 카메라가 제한될 경계 영역을 설정하는데 사용됩니다. Collider2D는 2D 모드에서 카메라가 움직일 수 있는 영역의 형태를 결정하는 컴포넌트입니다. 이 경계는 카메라가 벗어날 수 없도록 하여, 카메라가 이 경계를 넘지 않도록 합니다.

예를 들어, **BoxCollider2D**나 PolygonCollider2D 같은 콜라이더를 설정하여 카메라의 움직임을 제한할 수 있습니다.

2. m_ConfineMode

  • 타입: CinemachineConfiner.Mode
  • 설명: 이 프로퍼티는 카메라가 경계 내에서 어떻게 움직일지를 정의합니다. m_ConfineMode는 다음과 같은 모드를 설정할 수 있습니다:
    • Confine2D: 카메라가 2D 공간에서 제한되는 모드입니다. 카메라는 지정된 경계 내에서만 이동합니다.
    • Confine3D: 3D 공간에서 제한을 설정하는 모드로, 카메라의 Z축 이동도 제한할 수 있습니다.

3. m_Damping

  • 타입: float
  • 설명: 카메라가 경계를 벗어나려고 할 때, 얼마나 부드럽게 돌아오는지를 결정하는 값입니다. 값이 클수록 카메라가 경계에 도달한 후 더 부드럽게 되돌아옵니다.
  • 이 값은 경계를 넘을 때의 속도를 결정하며, 카메라가 경계를 벗어난 후 어떻게 복귀할지에 대한 느낌을 조절합니다.

4. m_ShowDebug

  • 타입: bool
  • 설명: 이 옵션을 활성화하면 디버그 정보를 화면에 표시합니다. 경계를 시각적으로 확인하고 싶을 때 유용합니다. 설정된 경계가 카메라에 어떻게 영향을 미치는지 실시간으로 확인할 수 있습니다.

5. m_ConfineScreenEdges

  • 타입: bool
  • 설명: 이 옵션을 활성화하면 카메라가 경계에 도달했을 때, 화면의 가장자리에서 더 이상 이동하지 않도록 설정할 수 있습니다. 이 설정을 켜면 카메라가 제한된 범위 밖으로 나가지 않도록 강제됩니다.

저도 처음 보는 거라 GPT한테 문의를 좀 해봤습니다!.... 그렇다고 하네요!

 

아무튼 콜라이더를 이용해서 카메라의 이동영역을 제한한다는 건 알겠습니다!

그러면 바로 콜라이더를 만들러 가보죠!

CameraConfiner Inspector

 

Grid에 빈오브젝트를 만들어서 CameraConfiner이라고 이름을 붙여주고 그 안에 Polygon Collider 2D를 붙여준 뒤에 트리거에 체크를 해줬습니다! 그리고 카메라의 영역을 제한할 곳을 Scene만큼 콜라이더로 잡아줬습니다!

 

이렇게 만들어줬는데 문제는 씬에 있는 Grid에 추가를 했더니 Essential씬에 있는 카메라가 이것을 참조할 수가 없다는 겁니다!

그리고 맵마다 이 영역을 지정해 준다고 해도 이것을 할당하는 게 쉽지는 않을 것 같다는 생각이 듭니다 맞나요??

이것을 해결하기 위해서 스크립트 파일을 하나 만들어줍니다! 이름은 CameraConfiner.cs로 했습니다!

CameraConfiner.cs

 

먼저 이렇게 게임오브젝트를 강제로 찾아서, 콜라이더를 가져오고 m_BoundingShape2D에 할당해 줍니다!

m_BoundingShape2D가 경계 영역을 설정하는 부분입니다!

 

이렇게 해서 실행시켜 주면

Game

 

카메라 영역이 제한된 걸 확인하실 수 있습니다!! 그런데 문제가 발생합니다!  만약에 CameraConfiner 오브젝트가 없다면 어떨까요? Null 에러가 뜨겠죠!? 그것을 해결하기 위해 가드절을 하나 만들어보겠습니다!

CameraConfiner.cs

 

맵에 카메라 제약이 없거나 실수로 카메라의 제약을 안 뒀거나 한다면 에러가 날 수 있으니 이렇게 널 체크를 해주시면 됩니다! 이렇게 하면 에러는 안 나오거든요!

 

그럼 이제 씬이 전환될 때 새로운 씬에 있을 CameraConfiner로 데이터를 교체해 줘야겠죠?

GameSceneManager.cs로 갑니다!

GameSceneManger.cs

 

카메라를 전환시키기 위해 참조변수를 하나 선언해 주고요!

GameSceneManger.cs/Transition()

 

트랜지션 메서드의 맨 하단부에 이렇게 적용시켜 줍니다!

아! 그리고 if else로 구분하던 screenTint.tintedTime은 사실상 하나로 가능해서 변경했습니다!

이렇게 적용해주고 나서 직렬화 변수를 추가해 준 다음에 게임을 확인해 보면요!

GameManager Inspector
Game

 

작동하지 않습니다. 왜 그런 걸까요?

저희가 씬을 전환할 때, 새로운 씬을 로드하고 기존의 씬을 비동기처리하는 방식을 사용했잖아요? 

그래서 비동기처리하기 전에 즉, 바뀌기 전의 씬에서 CameraConfiner를 계속해서 찾게 되는 겁니다!

 

이 문제를 해결하기 위해서는 비동기적 로드와 비동기적 언로드를 적절한 타이밍에 제대로 작동을 시켜주어야 합니다!

먼저 변수부터 추가해 주겠습니다! 

GameSceneManager.cs

 

AsyncOperation란?

더보기

AsyncOperation은 Unity에서 비동기적으로 작업을 처리할 때 사용되는 클래스입니다. 이 클래스는 씬 로드, 씬 언로드, 리소스 로드 등의 비동기 작업을 수행할 때 사용됩니다. Unity에서 비동기 작업을 처리할 때, UI 스레드를 차단하지 않고 작업을 수행할 수 있게 도와줍니다.

 

AsyncOperation 타입 변수:

  • AsyncOperation은 비동기 작업의 상태를 추적하고, 작업이 완료되었는지 확인할 수 있는 기능을 제공합니다.
  • 이 객체는 씬을 로드하거나 언로드하는 작업을 비동기적으로 처리할 때 주로 사용됩니다. AsyncOperation을 사용하면, 해당 작업이 완료될 때까지 다른 작업을 처리할 수 있습니다.

저희는 이 변수를 통해서 비동기적으로 로드와 언로드가 다 됐는지 확인하기 위해서 사용합니다!

 

사용법은 이렇습니다!

GameSceneManager.cs/SwitchScene()

 

먼저 LoadScene도 비동기적으로 바꿔주고 load 변수에 담습니다! unload도 동일하게 변수로 받아주시면 되구요!

GameSceneManager.cs/Transition()

 

그다음 Transition()메서드로 와서 비동기적 처리들이 끝날 때까지 루프를 돌려주면 됩니다!

while문 안에 흔하게 쓰이는 &&(논리 AND 연산자)가 아니라 &(비트 AND 연산자)를 사용하는데,

논리 AND인 &&는 위코드를 예시로 보면 load != null 이 false면 unload != null 부분을 체크하지 않습니다

하지만 비트 AND인 &는 항상 두 조건을 같이 검사한다는 차이가 있습니다!

(제 생각에는 그래도 &&를 써도 될 것 같다고 느끼는데 잘 모르는 부분이라 영상 따라가겠습니다!)

 

그래서 비동기적으로 씬들의 로드와 언로드가 끝나면 밑에 있는 코드들을 실행하도록 업데이트해줬습니다!

확인해 보면요?

Game

 

네 잘 되는 걸 확인하실 수 있습니다!

 

이편은 여기까지 하겠습니다! 감사합니다!

+ Recent posts