유니티 버전 - 2022.3.44f1
목차
- Audio Manager란?
- Audio Manager의 정의, Audio Source와의 관계
- 참조 레퍼런스
- Audio Manager의 코드 및 설명
- 코드
- 설명
- Audio Manager의 장점과 단점, 코드 개선점
- 장점
- 단점
- 개선점
- 코드 개선하기
- 개선점
- 완성된 코드 및 실행 결과
- 완성코드
- 설명
- 실행결과
- 마치며
- 간단 정리
- 참고하면 좋은 자료
Audio Manager란?
Audio Manager는 미리 정의된 Audio Source에 Audio Clip을 넣어서 소리를 재생시키도록 도와줍니다
기본적인 구조는 아래를 참고했습니다
Audio Manager의 코드 및 설명
한 블럭씩 나누어 아래에서 설명해겠습니다
커스텀 클래스 Sound는 앞으로 실행시키고자 하는 오디오의 정보를 담기위한 형식(그릇) 입니다
[System.Serializable]
public class Sound
{
public string name; // name을 통한 호출
public AudioClip clip;
}
선언부
public class AudioManager1 : MonoBehaviour
{
public static AudioManager1 instance;
[SerializeField] Sound[] sfx = null;
[SerializeField] AudioSource[] sfxPlayer = null;
[SerializeField] Sound[] bgm = null;
[SerializeField] AudioSource bgmPlayer = null;
sfx는 모든 Sound형식의 오디오를 해당 배열에 미리 등록시켜 놓는 역할 입니다
sfxPlayer는 미리 만들어놓은 Audio Source에 클립을 받아서 재생시키기 위한 역할 입니다
게임 bgm은 하나만 재생하기에 배열이 아닌 단독으로 선언 하였습니다
Awake()
private void Awake()
{
if (instance == null)
{
instance = this;
//DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
오디오 매니저를 싱글톤화하여 어디서든 호출할 수 있도록 해줍니다
PlayerSFX(string p_sfxName)
public void PlaySFX(string p_SfxName)
{
for (int i = 0; i < sfx.Length; i++) // 등록된 sfx[]에서 p_sfxName과 같은 name이 있는지 확인합니다
{
if (p_SfxName == sfx[i].name) // 만약 같은 name이 있다면 아래를 실행합니다
{
for (int j = 0; j < sfxPlayer.Length; j++) // Audio Source에 남은 자리가 있는지 확인합니다
{
if (!sfxPlayer[j].isPlaying) // 플레이어가 재생중이지 않다면 실행합니다
{
sfxPlayer[j].clip = sfx[i].clip; // 빈 Audio Source에 클립을 넣습니다
sfxPlayer[j].Play(); // 받은 클립을 실행시킵니다
return;
}
}
Debug.Log("모든 플레이어가 재생중"); // 플레이어에 빈 자리가 없다면 return 합니다
return;
}
}
Debug.Log(p_SfxName + "라는 효과음이 없음"); // 등록된 sfx[]에서 p_sfxName과 같은 name이 없다면 return합니다
return;
}
PlayerBGM(string p_bgmName)
public void PlayBGM(string p_BgmName)
{
for (int i = 0; i < bgm.Length; i++)
{
if (p_BgmName == bgm[i].name)
{
bgmPlayer.clip = bgm[i].clip;
bgmPlayer.Play();
return;
}
}
Debug.Log(p_BgmName + "라는 BGM이 없음");
}
bgmPlayer는 하나밖에 없기때문에 p_bgmName과 bgm.name을 비교하여 존재한다면 실행시킵니다
다음은 인스펙터에서 조작해야 할 것들입니다.
자식 오브젝트에 Audio Source를 배치하고 각자 맞는 Player로 매칭합니다, 인스펙터 창을 하나 더 열어 고정시켜서 진행해줍니다
Audio Source들의 속성을 적절하게 조절합니다
sfx나 bgm을 등록시키고 싶다면 배열을 주가하여 Name을 설정 후 Clip을 넣어줍니다
다른 클래스에서 소리를 재생시키고자할때는 아래의 방법으로 실행합니다
Audio Manager의 장점 및 단점, 코드 개선점
장점
- sfx와 bgm을 하나의 클래스에서 모두 관리하므로, 일관적인 관리 및 호출이 가능합니다
- 미리 정의된 AudioSource의 사용 가능한 자리를 찾아 효과음을 재생하는 효과적인 자원 관리가 가능합니다
단점
- 등록된 모든 오디오가 항상 필요한 것은 아님에도 준비되어 있는 오디오로 인해 메모리 낭비가 발생할 수 있습니다
- 모든 sfxPlayer가 재생중이라면 더 이상 새로운 sfx를 재생시킬 수 없습니다
코드 개선점
- 하드코딩된 파라미터 변수로 인한 휴먼 에러️ 가능성 존재
- 관리해야할 sfx의 갯수 증가로 인한 인스펙터의 복잡도 증가
완성된 코드 및 실행 결과
개선시킨 AudioManager입니다 아래에서 블럭으로 나누어 설명하겠습니다
커스텀 클래스 Sound<T>
public class Sound<T>
{
public T name;
public AudioClip clip;
}
제네릭 타입 매개변수를 이용하여 name을 미리 정의된 Enum으로 설정하여 변수로 문자열을 직접 넘겨주는 것이 아닌 enum 타입을 넘겨주어 잘못 전달할 가능성을 낮추었습니다
선언부
public class AudioManager : ConvertToSingleton<AudioManager>
{
[SerializeField] AudioSource musicPlayer = null;
[SerializeField] AudioSource[] sfxPlayer = null;
[Header("-------BGM-------")]
[SerializeField] Sound<Music>[] music = null;
[Header("-------SFX-------")]
[SerializeField] Sound<PlayerSFX>[] playerSFX = null;
[SerializeField] Sound<EnemySFX>[] enemySFX = null;
[SerializeField] Sound<EnemySFX>[] EmbientSFX = null;
[Header("")]를 이용하여 인스펙터에서 구역을 나누어 가독성을 향상 시켰습니다
[Space(int)]를 이용하여 요소들 사이에 더 공간을 둘수있습니다, 여백을 주고자하는 요소 바로 윗 줄에 선언합니다
enum 타입별로 sfx배열을 만들어 관리해야할 오디오 갯수 증가에따른 인스펙터상에서의 관리 효율을 증가시켰습니다
Awake()
protected override void Awake()
{
base.Awake();
DontDestroyOnLoad(gameObject);
}
싱글톤화 및 DontDestroyOnLoad()를 이용해 씬이 전환되어도 BGM이 끊기지 않도록 하였습니다
싱글톤화는 아래를 참고바랍니다
PlaySFX(Enum p_Enum)
public void PlaySFX(PlayerSFX p_PlayerSFX) // 파라미터 값이 다름
{
for (int i = 0; i < playerSFX.Length; i++)
{
if (p_PlayerSFX.Equals(playerSFX[i].name))
{
for (int j = 0; j < sfxPlayer.Length; j++)
{
if (!sfxPlayer[j].isPlaying)
{
sfxPlayer[j].clip = playerSFX[i].clip; // 파라미터에 따라 메서드별로 배열이 다름
sfxPlayer[j].Play();
return;
}
}
Debug.Log("모든 플레이어가 재생중");
return;
}
}
Debug.Log(p_PlayerSFX + "라는 효과음이 없음");
return;
}
3개의 메서드에서 로직은 기본적으로 동일하나 받은 Enum타입 별로 찾는 배열이 다릅니다
마치며
AudioManager를 통해 오디오 소스와 클립을 통합적으로 관리 및 운영하는 방법을 배웠습니다
하지만 한계점도 분명히 존재합니다
방향성이 필요한 오디오는 AudioManager가 아닌 바른 방법을 사용해야할 것 입니다
프로젝트의 상황에 맞게 적절하게 선택하는것이 필요합니다
아래는 AudioSource와 관련하여 참고하면 좋은 자료입니다
이상입니다.
'코드 및 공부 > 오디오' 카테고리의 다른 글
오디오 믹서 (2) (0) | 2024.09.19 |
---|---|
오디오 믹서 (1) (4) | 2024.09.18 |