SoundManager라는 빈오브젝트를 만들고 여기에 SoundManager 스크립트를 추가했다.
그리고 사용할 클립들을 모두 끼워 넣을 clip 배열과 이를 재생할 Play() 메서드를 작성했다.
장소에 따라 배경음악을 실행하도록
플레이어에게 BgmController 스크립트를 추가했다.
플레이어의 위치를 감지하기 위해 모래사장의 레이어를 "Sand"로 설정하고
CollisionEnter를 이용해 SoundManager의 인스턴스를 불러 오디오클립을 실행했다.
AudioSource
- 소리를 재생하는 플레이어
- 스피커
- 볼륨: 0 ~ 1
AudioClip
- 오디오 소스가 재생할 때 필요한 음원 파일(mp3, wav등)
AudioListener
- 소리를 듣는 주체
- 주로 메인 카메라에 AudioListener 컴포넌트가 기본으로 장착되어 있다.
AudioSource.Play()
AudioSource.PlayOnShot()
Play()
- 현재 설정된 오디오 클립을 재생
- 이미 오디오가 재생중이면 중지하고 새로운 오디오를 재생
- 반복 재생 및 특정 설정이 필요한 경우 사용
- 배경음악 실행할 때 좋을 것 같다
PlayOnShot()
- 단일 효과음 재생
- 현재 재생중인 오디오를 중단하지 않고 동시에 새로운 효과음을 추가로 재생
Sound 적용방법
SoundManager 오브젝트를 만들고 오디오 클립을 레퍼런싱한다
- 빈오브젝트 생성 > Rename "SoundManager"
- SoundManager 스크립트 생성 후 컴포넌트 추가
- 스크립트 내에 AudioSource 선언
- 사용할 클립들을 레퍼런싱
SoundManager 컴포넌트 구조

SoundManager.cs
1. 사운드를 재생할 AudioSource를 선언한다
2. 사용할 오디오 클립을 끼워 넣을 배열을 선언한다
3. 오디오 클립 이름을 비교해 플레이할 Play()를 작성한다
using UnityEngine;
public class SoundManager : MonoBehaviour
{
public static SoundManager Instance;
[Header("#BGM")]
public AudioClip[] bgmClips;
public float bgmVolume = 0.5f;
[SerializeField]
AudioSource bgmPlayer;
[Header("#SFX")]
public AudioClip[] sfxClips;
public float sfxVolume = 0.7f;
AudioSource sfxPlayer;
[Header("#UI")]
public AudioClip[] uiClips;
public float uiVolume = 0.7f;
AudioSource uiPlayer;
//플레이어의 움직임, 점프 관련
[Header("#Player")]
public AudioClip[] playerClips;
public float playerVolume = 0.7f;
AudioSource playerPlayer;
void Awake()
{
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(Instance);
}
else
{
Destroy(gameObject);
}
Init();
}
public void Init()
{
// 배경음 플레이어 초기화
GameObject bgmObject = new GameObject("BgmPlayer");
bgmObject.transform.parent = transform;
bgmPlayer = bgmObject.AddComponent<AudioSource>();
bgmPlayer.playOnAwake = false;
bgmPlayer.loop = true; // 배경음은 반복실행
bgmPlayer.volume = bgmVolume;
//bgmPlayer.clips = bgmClip;
// 효과음 플레이어 초기화
GameObject sfxObject = new GameObject("SfxPlayer");
sfxObject.transform.parent = transform;
sfxPlayer = sfxObject.AddComponent<AudioSource>();
sfxPlayer.playOnAwake = false;
sfxPlayer.volume = sfxVolume;
//UI 효과음 플레이어 초기화
GameObject uiObject = new GameObject("UIPlayer");
uiObject.transform.parent = transform;
uiPlayer = uiObject.AddComponent<AudioSource>();
uiPlayer.playOnAwake = false;
uiPlayer.volume = uiVolume;
//Player 소리 플레이어 초기화
GameObject playerObject = new GameObject("PlayerPlayer");
playerObject.transform.parent = transform;
playerPlayer = playerObject.AddComponent<AudioSource>();
playerPlayer.playOnAwake = false;
playerPlayer.volume = playerVolume;
}
public void PlaySound(AudioSource player, AudioClip[] AudioClips, string clipName)
{
AudioClip selectedClip = null;
foreach(AudioClip clip in AudioClips)
{
if (clip.name.Contains(clipName))
{
selectedClip = clip;
break;
}
}
if (selectedClip != null)
{
player.PlayOneShot(selectedClip);
} else
{
Debug.Log("\"" + clipName + "\" sound is Empty.");
}
}
//Sound Test
//public void Start()
//{
// PlaySound(bgmPlayer, bgmClips, "Beach");
// PlaySound(sfxPlayer, sfxClips, "Seagulls");
//}
//BGM
// 해변가
public void PlayBgmBeach()
{
PlaySound(bgmPlayer, bgmClips, "Beach");
}
//SFX
// 갈매기 소리
public void PlaySeagullsSound()
{
PlaySound(sfxPlayer, sfxClips, "Seagulls");
}
// 박쥐소리
public void PlayCaveSound()
{
PlaySound(sfxPlayer, sfxClips, "Cave");
}
//UI
// 아이템창 On/Off
public void PlayOnOffItemInventory()
{
PlaySound(uiPlayer, uiClips, "ItemInventory");
}
// 아이템 습득
public void PlayGetItem()
{
PlaySound(uiPlayer, uiClips, "GetItem");
}
//Player
// 걷기
public void PlayPlayerFootStep()
{
PlaySound(playerPlayer, playerClips, "PlayerFootStep");
}
// 달리기
public void PlayPlayerRun()
{
PlaySound(playerPlayer, playerClips, "PlayerRun");
}
}
BgmController.cs
플레이어 오브젝트에 추가할 스크립트
OnCollisionEnter와 Layer를 이용해 플레이어의 위치를 파악한다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BgmController : MonoBehaviour
{
string Sand = "Sand";
string Ground = "Ground";
int SandLayerNumber;
int GroundLayerNumber;
void Start()
{
SandLayerNumber = LayerMask.NameToLayer(Sand);
GroundLayerNumber = LayerMask.NameToLayer(Ground);
}
private void OnCollisionEnter(Collision other)
{
if (other.gameObject.layer == SandLayerNumber)
{
SoundManager.Instance.PlayBgmBeach();
} else if (other.gameObject.layer == GroundLayerNumber)
{
SoundManager.Instance.bgmPlayer.Stop();
SoundManager.Instance.PlayBgmForest();
}
}
}
느낀 점
PlaySound()를 보면 PlayOneShot()을 사용해 모든 클립을 재생한다.
나의 경우는 플레이어가 해변가로 이동하면 파도소리를 재생하고
숲으로 이동하면 풀벌레 소리가 나도록
플레이어가 위치한 장소에 따라 배경음악을 변경해야 했다.
그러다 보니 배경음악을 플레이할 때
기존에 실행 중이던 클립은 Stop() 처리하고 새로운 클립을 실행하도록 구현했다.
그런데 AudioSoure의 Play()를 사용하면 자동으로 실행 중인 오디오를 중지하고 새로운 클립을 재생한다고 한다.
따라서 겹쳐서 발생해도 괜찮은 효과음 등은 PlayOnShot()을 사용하고
1번에 1개의 음원만 들려야 하는 배경음악은 Play()를 사용하는 게 좋을 것 같다.
'Unity' 카테고리의 다른 글
| Prototype4: 플레이어를 따라가는 몬스터, normalized, Time.deltaTime (0) | 2024.03.05 |
|---|---|
| Prototype5: MonoBehavior, Awake(), Start(), this vs gameObject (0) | 2024.03.01 |
| Global Volume : 체력 닳는 효과 (Post Processing) (1) | 2023.11.29 |
| Unity 실시간 2D 기초 Challenge: Sprite pachinko (0) | 2023.06.28 |
| 벽돌 머티리얼 만들기, 통통 튀는 탄성 추가하기 (0) | 2023.06.23 |