간단한 방법 (동시에 플레이되는 소리의 종류가 한 가지밖에 없을 때)
AudioSource 컴포넌트를 이용하면 된다.
- 원하는 GameObject를 선택한 뒤, AudioSource 컴포넌트를 부착한다.
- 이 컴포넌트의 Audio Resource 부분에 소리 파일(Audio Clip)을 드래그해 넣는다. (소리 파일의 형식은 주로 .wav나 mp3이다)
- 이렇게 하면 플레이(게임 시작) 버튼을 누르자마자 지정한 소리가 나온다.
그러나 위의 간단한 방법에는 상당히 많은 문제가 있는데,
1. 원할 때 소리를 플레이할 수 없다는 것
2. 코드를 좀 짜서, 1번 문제를 해결했다고 하더라도, 두 종류 이상의 효과음을 한 번에 플레이할 수 없다. (한 효과음이 재생되고 있는 도중에, 다른 효과음이 나온다면, 재생되고 있던 효과음이 중단된다.)
그렇다면 보다 많은 종류의 효과음이 동시에 플레이될 수 있는 구조를 만들려면 어떻게 해야 할까?
구체적인 방법 (동시에 플레이되는 소리의 종류가 두 가지 이상일 때)
여러 개의 AudioSource 컴포넌트를 이용하면 된다.
그러나 많은 수의 AudioSource 컴포넌트를 각각의 GameObject에 붙이고, 관리하는 것은 매우 힘들기 때문에, AudioManager 객체를 하나 만들어줘야 한다.
다음은 AudioManager 클래스의 코드이다.
using Unity.VisualScripting;
using UnityEngine;
public class AudioManager : MonoBehaviour
{
[SerializeField] private AudioClip bgmClip;
private AudioSource bgmPlayer;
[SerializeField] private AudioClip[] sfxClips;
private AudioSource[] sfxPlayers;
private void Awake()
{
bgmPlayer = gameObject.AddComponent<AudioSource>();
bgmPlayer.clip = bgmClip;
sfxPlayers = new AudioSource[sfxClips.Length];
for (int i = 0; i < sfxClips.Length; i++)
{
sfxPlayers[i] = gameObject.AddComponent<AudioSource>();
sfxPlayers[i].clip = sfxClips[i];
}
}
private void Start()
{
PlayBGM();
}
private void PlayBGM()
{
bgmPlayer.loop = true;
bgmPlayer.Play();
}
public void PlaySFX(int index)
{
sfxPlayers[index].Play();
}
}
(참고로 "[SerializedField] private" <-- 이 구절은 private 멤버 변수를 public하게 Inspector 창에서 접근할 수 있도록 만들지만, 멤버 변수 자체는 private의 성질을 지니도록 하는 관용어구...와 같은 것이다. 이 코드를 볼 때는 간단하게 [SerializedField] private == public이라고 생각하면 된다. 아니면 그냥 신경쓰지 않아도 된다! 그냥 아무 의미가 없는 것으로 생각해도 코드를 이해하는 데는 아무런 지장이 없다!)
보통 Manager류 코드는 빈 객체(Empty GameObject)에다가 Manager용 스크립트만 부착해서 사용한다. AudioManager도 그런 식으로 사용할 것을 가정하고 만들었다.
bgm(배경음악) 관련 부분부터 보면 이해하기 편할 것이다.
bgm 관련 부분
- bgmClip 변수를 통해, AudioClip(소리 파일)을 받을 공간을 하나 형성해준다. (이 변수는 [SerializedField] private을 통해 형성되었기 때문에, Inspector 창에서 직접 소리 파일(wav, mp3)을 드래그해 넣을 수 있다.)
- bgmPlayer = gameObject.AddComponent<AudioSource>();를 통해 bgmPlayer 변수에 새로 생성한 AudioSource 컴포넌트를 할당(참조)해준다. 참고로 새로 생성한 AudioSource 컴포넌트는 AudioManager GameObject에 붙는다. (아까 말한 빈 객체에 붙는다.)
이렇게 하면 게임을 실행하자마자, "bgm용 AudioClip"만을 위한 AudioSource 컴포넌트가 AudioManager GameObject에 생성되게 된다.
그 이후, Start() 메서드와 PlayBGM() 메서드를 통해 배경음악을 재생해주면 된다. (참고로 AudioSource 컴포넌트는, 이 컴포넌트에 할당되어 있는 AudioClip(Audio Resource)을 반복재생(loop)할지 결정할 수 있다. 그게 bgmPlayer.loop = true;로 표현된 것이다.)
sfx 관련 부분
(bgm 관련 부분과 거의 같다. bgm은 Audio Clip이 하나고, sfx는 여러 개라는 것이 유일한 차이점이다.)
- sfxClips 배열을 통해, AudioClip(소리 파일)들을 받을 공간을 하나 형성해준다. (이 배열은 [SerializedField] private을 통해 형성되었기 때문에, Inspector 창에서 직접 소리 파일(wav, mp3)을 드래그해 넣을 수 있다.)
- sfxPlayers = new AudioSource[sfxClips.Length];를 통해 sfxClip의 개수만큼 sfxPlayer(AudioSource 컴포넌트)를 위한 공간을 만들어준다. --> 이는 각각의 sfxClip을 위한 AudioSource 컴포넌트를 AudioManager에 부착하기 위함이다.
- for문을 통해, sfxPlayers[i]에 AudioSource 컴포넌트를 "각각" 할당한다. 그 뒤, sfxPlayers[i]의 Audio Resoure(Audio Clip)을 sfxClips[i]로 설정해준다.
이렇게 하면 게임을 실행하자마자, "sfx용 AudioClip"만을 위한 AudioSource 컴포넌트가 AudioManager GameObject에 생성되게 된다.
그 이후, Start() 메서드와 PlaySFX() 메서드를 통해 배경음악을 재생해주면 된다.
예를 들어, 만약에 Player가 점프할 때 소리를 플레이하고 싶다? 그러면..
- private AudioManager am;
- private void Awake() { am = FindFirstObjectByType<AudioManager>(); }
- public void Jump() { am.PlaySFX(5); }
위와 같은 방식으로 해주면 된다. (만약에 PlaySFX(숫자) 이런 형식이 불편하다면, enum을 사용할 수도 있다.)