소개
이 글은 제이터 (루오하오) 쉬(Jater (Ruohao) Xu)가 '역붕괴: 베이커리 작전(Reverse Collapse: Code Name Bakery)'에서 진행한 작업을 공유하는 3부작 기술 블로그 시리즈의 두번째 글입니다. 첫번째 글은 여기에서 확인할 수 있으며, Wwise를 활용한 인게임 시네마틱 제어 방법에 대해 자세히 다룹니다. 3부도 많은 기대 부탁드립니다!
기울어진 2D 뷰를 위한 커스터마이징 Wwise 리스너 위치 프로젝션 시스템
기술 블로그 시리즈 | 제 2부
역붕괴는 독특한 아트 스타일이 특징이며, 게임을 돋보이게 만드는 연출 중 하나로 기울어진 2D 레벨 맵을 사용합니다. 이 게임을 처음 보면, 2D 탑다운(top-down) 시점으로 느껴집니다. 하지만 실제로는 각 맵 레벨이 카메라가 바라보는 방향에서 살짝 기울어진 형태로 세심하게 제작되어 있습니다.
일반적인 탑다운 뷰의 3D 오디오 구현은 비교적 간단합니다. 하지만 역붕괴와 같이 기울어진 2D 탑다운 뷰를 사용하는 경우, 기본적인 3D 오디오 시스템만으로는 정확한 결과를 얻기 어렵습니다. 처음에는 기본 시스템을 적용해 봤지만, 카메라를 좌우 또는 상하로 이동할 때 감쇠(attenuation) 관련 버그가 발생했습니다.
이를 해결하기 위해서는 기본 3D 오디오 시스템을 조정하여 기울어진 2D 탑다운 뷰에 맞는 커스터마이징된 시스템이 필요했습니다.
위 이미지를 보면 문제를 정확히 확인할 수 있습니다. 카메라 뷰의 절두체(frustum)를 기준으로 맵이 기울어져 보이기 때문에 기본 오디오 감쇠에 오차가 발생합니다.
이 솔루션은 Unity의 게임 오브젝트, 스크립트, Wwise RTPC를 활용해 오디오 전용으로 투영된 X,Y,Z 좌표계를 만드는 간단한 프로젝션 시스템입니다. 맵을 회전한 후 오디오 리스너의 위치를 기본 카메라에서 변환된 위치로 옮겨 원하는 목표를 달성할 수 있었습니다. 이 방식은 기본 Wwise 오디오 감쇠 시스템과 자연스럽게 통합됩니다. 또한, Wwise RTPC를 통해 감쇠 범위를 수동으로 조정해야 하는 특수한 상황에서도 커스터마이징된 좌표계를 그대로 활용할 수 있습니다.
이를 위해 먼저 아래 영상에서 마젠타색 큐브로 표시된 투영 위치를 프리팹(prefab) 게임 오브젝트로 설정해야 합니다. 이 게임 오브젝트는 기본 카메라와 고정된 오프셋(offset) 거리를 유지하면서 어떤 카메라에도 부착할 수 있어야 합니다. 게임 내 여러 개의 카메라 설정이 존재하기 때문에 이 게임 오브젝트는 반드시 프리펩으로 만들어야 합니다. 따라서 런타임 중에 각 카메라 설정에 맞게 이 게임 오브젝트의 하위로 프로젝션 시스템을 유연하게 설치하거나 전환할 수 있어야 합니다. 하지만 이 단계는 모든 프로젝트에 동일하게 적용되지 않을 수 있습니다.
투영 위치에 사용할 프리팹 게임 오브젝트를 설정한 후, 다음 단계는 Wwise Unity 통합에 포함된 AkAudioListener.cs 스크립트를 이 프리펩의 상위 오브젝트에 추가하는 것입니다. 이 작업을 통해 해당 오브젝트는 게임의 오디오 리스너로 지정됩니다. 그 다음으로는 MainCamera 게임 오브젝트에서 기본 Audio Listener 컴포넌트를 제거해야 합니다.
위 이미지는 사운드 프로젝션 시스템에 사용된 특별한 오디오 리스너 게임 오브젝트의 프리펩 설정을 보여줍니다. 이 오브젝트에는 SoundProjectSampler라는 이름을 붙였습니다.
위 영상은 카메라 시점으로 보는 맵을 보여주며 엔진 내에서 최종 구현된 시스템의 동작 모습도 함께 보여줍니다.
Wwise에서는 Unity로부터 전달받은 좌표 데이터를 활용할 RTPC를 설정합니다. 이를 통해 사운드를 원하는 대로 수정하여 결과를 얻을 수 있습니다. 각 RTPC의 구체적인 범위는 각 게임 맵의 단위 크기에 따라 달라집니다. 이 게임의 경우 범위를 0에서 100 사이로 설정했습니다.
카메라 오브젝트에는 앞서 설명한 방식과 마찬가지로 스크립트를 적용하고, 해당 RTPC 호출을 LateUpdate() 함수 내에 포함합니다. 물론 Update() 함수에서도 동작하지만, LateUpdate() 를 사용하면 오디오 좌표 업데이트 전에 모든 렌더링 작업이 완료되도록 보장할 수 있습니다. 이러한 순서 덕분에 오디오와 비주얼 간 동기화를 유지할 수 있습니다.
AkSoundEngine.SetRTPCValue(CameraDistance_X, Normalization(soundProjectionSampler.transform.position.x, 0.0f, 100.0f));
AkSoundEngine.SetRTPCValue(CameraDistance_Y, Normalization(soundProjectionSampler.transform.position.y, 0.0f, 100.0f));
AkSoundEngine.SetRTPCValue(CameraDistance_Z, Normalization(soundProjectionSampler.transform.position.z, 0.0f, 100.0f));
위 솔루션에서 Normalization() 헬퍼 함수를 사용했는데 이 함수는 최소값과 최대값 범위를 기준으로 주어지는 부동소수점 값을 0에서 1사이의 범위로 변환하는 역할을 합니다. 사용하는 RTPC의 범위를 통일하기 위해 이와 같은 헬퍼 함수를 사용하는 것이 매우 유용합니다. 이 함수는 아래의 정규화(normalization) 공식으로 간단하게 작성할 수 있습니다.
정규화 값 = (정규화할 값 - 최소값) / (최대값 - 최소값)
정규화 구현 예제는 C#과 C++을 포함한 다양한 프로그래밍 언어에서 쉽게 찾아볼 수 있습니다. 온라인에서 간단히 검색만으로도 충분한 자료를 얻을 수 있으므로 이 글에서는 따로 다루지 않겠습니다.
이 RTPC를 연동하면 기본 Wwise 감쇠 시스템을 통해 정확한 오디오 결과를 얻을 수 있습니다. 또한, 각 오디오 음원에 X, Y, Z 좌표 RTPC를 직접 적용함으로써 사운드를 개별적으로 세밀하게 조정할 수 있는 유연성도 얻게 됩니다. 이를 통해 사운드 디자이너는 자신만의 감쇠 시스템을 설정하거나, 기본 감쇠 시스템을 확장하여 사용할 수 있습니다.
이 예시는 3009 게임플레이 레벨에서 감염체가 수류탄에 의해 점화될 때 사운드가 어떻게 감쇠되는지를 보여줍니다. 초기에는 감염체 사운드를 Wwise의 기본 감쇠 기능을 활용한 3D 사운드로 설정했습니다. 또한, 이 감쇠는 직접 만든 투영 좌표(projected coordinate)에 의해 제어되므로 정확한 게임 맵 단위에 따라 사운드 감쇠를 커스터마이징하고 세부 조정할 수 있습니다.
기존의 감쇠 프로파일과 함께 사용할 수도 있고, X, Y, Z 좌표 RTPC는 게임 오브젝트 범위의 사운드에 대해 감쇠 효과를 독립적으로 생성할 수도 있습니다. 사운드 디자이너는 맵의 각 축(X, Y, Z)에 대응하는 사운드를 세밀하게 조정할 수 있으며, 이를 통해 '역붕괴' 게임과 같은 독특한 맵 구도에서도 더욱 정밀한 음향적 결과를 얻을 수 있습니다.
이러한 유연성 덕분에 사운드 디자이너는 게임의 시각적 요소를 보완하고 전반적인 게임 플레이 분위기를 향상시키는 몰입감 있는 오디오 경험을 만들어낼 수 있습니다.
알림: 이 글에서 사용된 코드 예제들은 설명을 위해 일반화하여 재구성된 버전입니다. 기본 로직은 정상적으로 동작하는 것이 검증되었으며, 특정 프로젝트에 특화된 API 호출과 함수들은 저작권 문제로 인해 예제에서 생략되었습니다.
댓글