내일배움캠프 92일차 - 언리얼 C++ 멀티플레이 팀프로젝트: 미니게임파티 7~8일차
언리얼엔진5 C++ 기반 멀티플레이 게임 팀 프로젝트 제작
작업내용 요약
본인 탈락시 카메라 시점 연출 보여주기 및 관전자용 카메라로 전환
탈락 카메라 연출 추가
| 기존 탈락자 시점(1P)와 다른 플레이어 시점(2P) |
나는 이 문제를 주말에 분석하면서 해결방안을 모색했다.
| 탈락 연출 함수 |
기존 탈락 연출 함수의 경우 해당 APlayerController를 가지고 있는 PC(서버, 탈락한 클라이언트) 일때, 탈락자 카메라로 전환되는 함수 DeathCamFollowCharacter()를 실행하였다.
해당 함수에서는 카메라의 위치와 각도를 변경하는 SetWorldLocation(), SetWorldRotation()을 실행하였었는데, 왜 위치가 초기화되지 않았던 것일까? 나는 이 현상에 대해 중단점과 로그를 여러 개 찍어보면서 "혹시나?" 하는 마음에 탈락연출 RPC함수 대상을 Multicast가 아닌 Client로 바꿔보기도 하였다.
| MulticastRPC에서 ClientRPC로 시험삼아 변경해보았다. |
| 탈락자 시점(1P)와 다른 플레이어 시점(2P) |
그 결과 다른결과가 나왔는데, 탈락자 시점에서 카메라의 위치, 각도변경이 제대로 작동하여 탈락자를 제대로 화면에 비추는 결과가 나왔다. (다만 탈락 대상자에게만 호출되는 ClientRPC기 때문에 다른 플레이어 시점에서는 탈락자가 튀어오르는 효과가 연출되지 않는다)
왜 이런 결과가 발생한 것일까? 서버와 클라이언트가 동시에 트랜스폼을 변경하면 트랜스폼값이 적용되지 않고, 반대로 클라이언트만 받으면 트랜스폼이 적용된다니. 이에 대해서 나는 자료를 검색하던중, 구글 Gemini에 의해 어느 정도의 답을 들을 수 있었다.
| Gemini의 답변 |
요컨데, Pawn은 bReplicate = true가 기본 값인 액터고, 리플리케이트 된 액터는 서버와 클라이언트에서 동시에 값을 변경하면 값 충돌로 인해 둘 다 무시(Drop)될 가능성이 높다는 것이다. 따라서 서버가 트랜스폼 값 변경을 전담해야 한다는 것인데, 이 경우 전달 과정에서 지연이 발생해 값이 늦게 적용될 수 있다는 우려가 있다.
동기화 지연을 피하기 위해 "클라이언트만 값을 바꾸면 되지 않나?" 라고 생각하였으나, 이 경우 어느 순간 서버의 값으로 리플리케이트 되어 덮어씌워지는 러버밴딩(rubber banding) 현상이 발생한다고 한다. 러버밴딩은 멀티플레이 게임을 할때, 네트워크 상태가 좋지 않으면 이동 중에 캐릭터가 고무줄처럼 이동방향으로 왔다갔다하는 현상을 일컫는다.
나는 여기서 "관전자 카메라는 내 PC에만 영향을 미치니까 내 클라이언트에서만 생성하면 된다"고 판단하여 로컬 컨트롤러일때만(IsLocalController() == true) 관전자 카메라를 스폰하도록 로직을 구성하였다. 이렇게 하면 서버가 간섭할 일이 없으므로 클라이언트에서 트랜스폼 값을 변경하면 된다.
결과적으로, 탈락자 시점에서는 카메라가 잘 작동하고 있으며, 타 클라이언트는 탈락자가 폭발에 휘말리는 연출이 보이는 것을 확인할 수 있었다.
관전자 카메라 전환
탈락 후에는 관전자로 전환된다. 관전자로 전환되면 아직 생존중인 플레이어를 관찰하게 되는데, 이를 구현하기위해 AGameMode에서 사용되던 생존 플레이어 리스트를 가져오기로 한다.
| GameStateBase.h |
이후 관전자 전환 시 GameState에서 생존 중인 캐릭터들을 가져와 그 중 하나에 카메라를 Attach하면 된다.
또한 새 탈락자가 발생할 때 탈락자의 메시가 관전중인 캐릭터의 메시와 일치하면 다시한번 관전자 전환을 실시한다.
댓글
댓글 쓰기