FMOD 사용법 #Unity

게임에서 사운드는 단순히 AudioClip을 재생하는 것 이상으로 복잡하다.

게임의 규모가 커지면 다음과 같은 요구사항이 생긴다.

  • 상황에 따라 다른 효과음 재생
  • 같은 효과음의 랜덤 Variation
  • 거리 기반 3D 사운드
  • 전투 상태에 따른 음악 변화
  • 게임 상태에 따른 음악 강도 변화
  • 자연스러운 음악 Transition
  • Reverb와 공간감
  • 사운드 믹싱
  • 런타임 Parameter에 따른 사운드 변화

Unity의 기본 AudioSource만으로도 구현할 수 있지만, 규모가 커질수록 오디오 로직이 게임 코드에 섞이기 쉽다.

이 문제를 해결하기 위해 사용하는 대표적인 오디오 미들웨어가 FMOD다.

FMOD란?

FMOD는 게임과 인터랙티브 콘텐츠를 위한 Audio Middleware다.

Unity에서 직접 오디오를 제어하는 대신, 오디오의 구성과 동작을 FMOD Studio에서 설계하고 Unity에서는 게임의 상태나 이벤트를 전달하는 방식으로 사용할 수 있다.

구조는 다음과 같다.

Unity
  │
  │ 게임 상태 전달
  ▼
FMOD Integration
  │
  ▼
FMOD Studio
  │
  ├─ Event
  ├─ Parameter
  ├─ Bus
  ├─ Mixer
  ├─ Snapshot
  ├─ Timeline
  └─ 3D Audio

즉 프로그래머는 게임의 상태를 전달하고, 오디오 디자이너는 FMOD에서 사운드의 실제 동작을 설계할 수 있다.


Unity 기본 AudioSource와 FMOD의 차이

Unity에서는 일반적으로 다음과 같이 사운드를 재생한다.

audioSource.PlayOneShot(attackSound);

게임이 복잡해지면 코드에서 다음과 같은 요소를 직접 관리하게 된다.

AudioClip
Volume
Pitch
Loop
Random
3D Position
Mixer
Fade
Reverb
Transition

반면 FMOD에서는 사운드 자체를 하나의 Event로 구성한다.

예를 들어:

event:/Player/Attack
event:/Player/Footstep
event:/Weapon/Sword
event:/Monster/Roar
event:/Music/Battle

Unity에서는 해당 Event를 호출하기만 하면 된다.

RuntimeManager.PlayOneShot("event:/Player/Attack");

Event 내부에서 어떤 사운드를 재생할지, 어떤 조건에서 변형할지는 FMOD Studio에서 관리한다.


FMOD 설치

FMOD를 Unity에서 사용하려면 크게 두 가지가 필요하다.

FMOD Studio
FMOD Studio Unity Integration

FMOD Studio에서 오디오 프로젝트를 만들고, Unity에는 FMOD Integration을 설치한다.

설치가 완료되면 Unity 프로젝트에 FMOD 관련 기능이 추가된다.

일반적으로 다음과 같은 형태로 사용할 수 있다.

Unity Project
├─ Assets
│  └─ Plugins
│     └─ FMOD
│
└─ FMOD Studio Project

프로젝트 구조와 메뉴는 사용하는 FMOD 버전에 따라 조금씩 달라질 수 있다.


FMOD 프로젝트 만들기

FMOD Studio에서 새로운 프로젝트를 만든다.

예를 들어 프로젝트 이름을 다음과 같이 설정할 수 있다.

MyGameAudio

이제 게임에서 사용할 Event를 만든다.

예를 들어 플레이어 공격 효과음을 만든다고 하면:

Events
└─ Player
   └─ Attack

Event의 경로는 다음과 같이 된다.

event:/Player/Attack

이 Event에 실제 공격 효과음 파일을 넣는다.

event:/Player/Attack
        │
        ├─ Attack_01.wav
        ├─ Attack_02.wav
        └─ Attack_03.wav

여기서 FMOD의 장점이 나타난다.

동일한 공격을 여러 번 실행할 때 항상 같은 파일이 재생되도록 만들 필요가 없다.

여러 사운드를 Variation으로 구성하여 반복감을 줄일 수 있다.


Event란?

FMOD를 이해하려면 Event를 이해하는 것이 가장 중요하다.

Event는 단순한 AudioClip이 아니다.

하나의 Event 안에 다음과 같은 요소를 구성할 수 있다.

Event
├─ Audio
├─ Volume
├─ Pitch
├─ Parameter
├─ Automation
├─ Spatialization
├─ Loop
└─ Transition

예를 들어 검을 휘두르는 사운드라면:

event:/Weapon/Sword/Swing

하나의 Event 안에 여러 효과음을 넣을 수 있다.

Sword Swing
├─ Swing Sound
├─ Whoosh
├─ Impact
└─ Random Variation

Unity에서는 이 Event 하나만 호출하면 된다.


Unity와 FMOD 연결

FMOD Integration이 설치되면 Unity에서 FMOD 관련 API를 사용할 수 있다.

가장 간단한 형태는 다음과 같다.

using FMODUnity;

public class Player : MonoBehaviour
{
    public void Attack()
    {
        RuntimeManager.PlayOneShot("event:/Player/Attack");
    }
}

공격할 때:

Attack();

FMOD Event가 재생된다.

이것이 Unity + FMOD의 가장 기본적인 구조다.


EventReference 사용하기

문자열로 Event 경로를 직접 작성하는 것보다 EventReference를 사용하는 방법이 좋다.

using UnityEngine;
using FMODUnity;

public class Player : MonoBehaviour
{
    [SerializeField]
    private EventReference attackSound;

    public void Attack()
    {
        RuntimeManager.PlayOneShot(attackSound, transform.position);
    }
}

그러면 Unity Inspector에서 FMOD Event를 직접 지정할 수 있다.

Player
└─ Attack Sound
   └─ event:/Player/Attack

이 방식의 장점은 Event 경로를 코드에 문자열로 직접 작성하지 않아도 된다는 것이다.


3D 사운드 재생

FMOD는 3D Audio를 쉽게 사용할 수 있다.

RuntimeManager.PlayOneShot(
    attackSound,
    transform.position
);

두 번째 인자로 위치를 전달하면 해당 위치에서 사운드가 발생한다.

예를 들어:

Enemy
  🔊
   │
   │
   │
Player
  👤

플레이어와 적의 거리가 멀어지면 FMOD에서 설정한 Spatial Audio 규칙에 따라 소리가 작아진다.

Unity에서 직접 거리 계산을 하지 않아도 된다.


FMOD Parameter

FMOD의 강력한 기능 중 하나가 Parameter다.

Parameter를 사용하면 게임의 데이터를 오디오 변화와 연결할 수 있다.

예를 들어 자동차 엔진을 구현한다고 하자.

RPM
0 ─────────────── 8000

FMOD에서 RPM이라는 Parameter를 만든다.

그리고 RPM 값에 따라 서로 다른 엔진 사운드를 자연스럽게 전환하도록 구성할 수 있다.

Unity에서는:

engineInstance.setParameterByName("RPM", rpm);

처럼 값을 전달한다.

결과적으로:

RPM 1000
→ 낮은 엔진음

RPM 3000
→ 중간 엔진음

RPM 6000
→ 높은 엔진음

RPM 8000
→ 고RPM 엔진음

이런 변화가 자연스럽게 이어진다.


Unity에서 Parameter 전달하기

먼저 FMOD Event를 재생하고 Instance를 가지고 있어야 한다.

private FMOD.Studio.EventInstance engineInstance;

초기화:

private void Start()
{
    engineInstance =
        RuntimeManager.CreateInstance(engineSound);

    engineInstance.start();
}

게임에서 RPM을 계산한 뒤:

engineInstance.setParameterByName("RPM", rpm);

값을 전달한다.

더 이상 Unity에서 여러 AudioSource의 Pitch를 직접 조작할 필요가 없다.

오디오 변화 자체는 FMOD에서 관리한다.


EventInstance

PlayOneShot()은 한 번 재생하고 끝나는 효과음에 적합하다.

예를 들어:

RuntimeManager.PlayOneShot(attackSound);

반면 지속적으로 제어해야 하는 사운드는 EventInstance를 사용하는 것이 좋다.

대표적인 예가:

Engine
Footsteps
Wind
Rain
Ambient
Music
Charging Sound

등이다.

예:

private FMOD.Studio.EventInstance musicInstance;

private void Start()
{
    musicInstance =
        RuntimeManager.CreateInstance(musicEvent);

    musicInstance.start();
}

이제 해당 Instance를 가지고 Parameter를 변경하거나 정지할 수 있다.

musicInstance.setParameterByName("Intensity", 0.8f);

종료할 때는:

musicInstance.stop(
    FMOD.Studio.STOP_MODE.ALLOWFADEOUT
);

musicInstance.release();

처럼 정리할 수 있다.


게임 상태와 음악 연결

FMOD를 사용하면 게임 상태를 음악과 직접 연결할 수 있다.

예를 들어:

Game State
│
├─ Exploration
├─ Combat
├─ Boss
└─ Victory

각 상태를 Parameter 또는 Logic으로 연결할 수 있다.

예를 들어 CombatIntensity라는 Parameter를 만들면:

0.0
│
├─ 평상시
│
0.5
│
├─ 일반 전투
│
1.0
│
└─ 보스 전투

게임에서는:

musicInstance.setParameterByName(
    "CombatIntensity",
    intensity
);

처럼 값을 전달한다.

그러면 음악의 레이어나 분위기를 FMOD가 자동으로 변경할 수 있다.


Snapshot

FMOD의 Snapshot도 중요한 기능이다.

Snapshot은 특정 상황에서 전체적인 오디오 환경을 변경하는 데 사용할 수 있다.

예를 들어 플레이어가 메뉴를 열었다고 하자.

게임 플레이
↓
Pause Menu

메뉴가 열렸을 때:

BGM ↓
SFX ↓
UI Sound ↑

와 같은 처리를 할 수 있다.

또는 동굴에 들어갔을 때:

Reverb ↑
Ambient 변화

와 같은 공간 효과를 적용할 수도 있다.

게임 코드에서 각각의 AudioSource 볼륨을 직접 변경하는 대신 FMOD의 Snapshot으로 오디오 상태를 관리할 수 있다.


FMOD에서 Bus를 사용하는 이유

게임의 사운드는 보통 카테고리별로 관리한다.

Master
├─ Music
├─ SFX
├─ UI
├─ Voice
└─ Ambience

이러한 오디오 그룹을 FMOD의 Bus로 구성할 수 있다.

예를 들어 옵션에서:

Music Volume
SFX Volume
Voice Volume

을 조절한다고 하자.

Unity에서는 각각 FMOD Bus의 볼륨을 변경하면 된다.

musicBus.setVolume(volume);

이렇게 하면 수많은 AudioSource를 하나씩 관리할 필요가 없다.


FMOD Bank

FMOD에서 생성한 Event와 오디오 리소스는 게임에서 사용할 수 있도록 Bank로 관리한다.

예를 들어:

Master Bank
Master Strings Bank
SFX Bank
Music Bank
Voice Bank

처럼 분리할 수 있다.

게임의 규모가 커지면 모든 오디오를 한꺼번에 로드하는 것보다 필요한 Bank만 로드하는 방식이 유리하다.

예를 들어:

메인 메뉴
→ Menu Bank

게임 시작
→ Gameplay Bank

보스 스테이지
→ Boss Bank

처럼 구성할 수 있다.

이것은 메모리 관리와 로딩 최적화에도 연결된다.


FMOD를 사용할 때의 역할 분리

FMOD의 가장 큰 장점은 프로그래머와 사운드 작업의 책임을 분리할 수 있다는 것이다.

기존 구조:

프로그래머
│
├─ AudioSource
├─ AudioClip
├─ Volume
├─ Pitch
├─ Mixer
├─ Fade
├─ Random
└─ Transition

FMOD 구조:

프로그래머
│
└─ 게임 상태 전달
       │
       ▼
    FMOD Event
       │
       ├─ Audio
       ├─ Parameter
       ├─ Automation
       ├─ Mixer
       ├─ Transition
       └─ Spatial Audio

프로그래머는 게임 로직에 집중하고 오디오의 세부적인 동작은 FMOD에서 관리할 수 있다.


실제 Unity 프로젝트에서는 어떻게 구성할까?

프로젝트 규모가 커진다면 다음과 같은 구조를 추천할 수 있다.

Audio
├─ SFX
│  ├─ Player
│  ├─ Weapon
│  ├─ Enemy
│  └─ Environment
│
├─ Music
│  ├─ Main
│  ├─ Battle
│  └─ Boss
│
├─ UI
│  ├─ Button
│  ├─ Popup
│  └─ Notification
│
└─ Ambience
   ├─ Forest
   ├─ Cave
   └─ City

FMOD Event도 같은 구조를 유지한다.

event:/SFX/Player/Attack
event:/SFX/Weapon/Sword
event:/SFX/Enemy/Dragon/Roar

event:/Music/Main
event:/Music/Battle
event:/Music/Boss

event:/UI/Button/Click

Unity에서는 EventReference를 통해 해당 Event를 연결한다.


FMOD를 사용해야 하는가?

모든 Unity 프로젝트에 FMOD가 필요한 것은 아니다.

간단한 게임이라면 Unity Audio만으로 충분하다.

작은 프로젝트
→ Unity AudioSource

하지만 다음과 같은 프로젝트라면 FMOD를 고려할 가치가 높다.

대규모 게임
인터랙티브 음악
복잡한 사운드 시스템
많은 효과음
3D Audio
동적 음악
다양한 게임 상태
오디오 디자이너와 협업

특히 음악이 게임 플레이와 강하게 연결되는 게임에서는 FMOD의 가치가 커진다.


Unity + FMOD의 핵심 구조

결국 핵심은 이것이다.

Unity
│
│ 게임 이벤트
│
├── Player Attack
├── Enemy Death
├── Enter Combat
├── Boss Start
└── Player Speed
        │
        ▼
     FMOD
        │
        ├── Event
        ├── Parameter
        ├── Snapshot
        ├── Bus
        ├── Bank
        └── Spatial Audio
        │
        ▼
      Sound

Unity가 게임의 상태를 정의하고,

FMOD가 그 상태에 따라 소리가 어떻게 변화할지를 정의한다.

따라서 FMOD를 단순한 AudioSource 대체품으로 이해하면 부족하다.

FMOD의 핵심은 게임의 상태와 오디오를 연결하는 인터랙티브 오디오 시스템을 구축하는 데 있다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다