
팀원분들이 작성한 코드를 통한 사운드 설정 만들기
BGMOPtion클래스와 SoundTest만 내가 구현.
여기에서 저번과 같이 슬라이더 값과 SoundManager의 BGMVolume 프로퍼티를
연결하여 슬라이더를 조절하면 사운드가 커지거나 줄어들거나 한다.
using UnityEngine;
using UnityEngine.UI;
public class BGMOption : MonoBehaviour
{
[SerializeField] private Slider bgmSlider; // BGM 슬라이더
private float prevBGMValue;
private void Reset()
{
bgmSlider = this.TryGetComponent<Slider>();
}
void Awake()
{
bgmSlider.onValueChanged.AddListener(SetBGMVolume);
}
public void SetBGMVolume(float value) // BGM 소리크기 설정
{
SoundManager.Instance.BGMVolume = value;
}
}
=======
슬라이더를 조절하면 사운드가 변하는 테스트 하기위한 스크립트.
빈 오브젝트에 이 스크립트를 넣고 버튼을 누르면 사운드 출력.
슬라이더를 조절하면 인스펙터에서 BGM, SFX, Master의 볼륨이
조절되는 것을 볼 수 있다.
SoundManager.Instance.PlayBGM("bgmusic"); 이 부분에서 사운드를 재생한다.
using UnityEngine;
using NaughtyAttributes;
public class SoundTest : MonoBehaviour
{
public float BGM;
public float SFX;
public float Master;
private void Update()
{
BGM = SoundManager.Instance.BGMVolume;
SFX = SoundManager.Instance.EffectVolume;
Master = SoundManager.Instance.MasterVolume;
}
[Button]
public void BGMTest()
{
SoundManager.Instance.PlayBGM("bgmusic");
}
[Button]
public void SFXTest()
{
SoundManager.Instance.PlaySound(transform,"24_orc_death_spin");
}
}
========
이 스크립트에서는 BGMVolume같은 프로퍼티 PlaySound(), PlayBGM()만 사용하였다.
여기 프로퍼티를 BGMOption클래스에서 불러와 값을 넣어줌.
get (읽기):
BGMVolume의 값을 읽어올 때, 내부 변수인 bgmVolume에 masterVolume을 곱한 값을 반환.
즉, BGM 볼륨은 전체 마스터 볼륨의 영향을 받아 최종적으로 결정.
set (쓰기):
BGMVolume에 값을 할당할 때(예: 슬라이더로 조절할 때), 다음 세 가지 단계를 거침.
값 제한:
할당하려는 value가 0보다 작으면 0으로, 1보다 크면 1로 제한. (볼륨은 보통 0에서 1 사이의 값을 가짐.)
내부 변수 저장:
제한된 value를 내부 변수 bgmVolume에 저장.
실제 오디오 반영:
bgmPlayer.volume = BGMVolume; 코드를 통해 bgmPlayer (배경 음악을 재생하는 AudioSource 컴포넌트)의
실제 볼륨을 방금 설정된 BGMVolume 값(여기서 다시 masterVolume이 곱해진 최종 값)으로 즉시 업데이트.
요약하자면, 이 BGMVolume 속성은 배경 음악의 볼륨을 안전하게 설정(0~1 범위 제한)하고,
설정된 값이 즉시 게임 내 실제 배경 음악에 반영되도록 하며, 마스터 볼륨과의 연동을 처리
SoundTest 클래스에서 SoundManager.Instance.PlayBGM("bgmusic");를
호출.
using System.Collections.Generic;
using UnityEngine;
//const string으로 이름을 저장해두기 열거대신에 해보기
//이걸 키값으로 사운드소스 를 가지는 오브젝트 딕셔너리
//이걸 꺼내 쓰기
//호출할때마다 로드
public class SoundManager
{
private static SoundManager instance;
//사운드 직접 재생할 오브젝트 리스트
//private static List<GameObject> soundPlayers = new List<GameObject>(); //3D사운드, 범위 조절에 대해서는 의논 필요 ,DDO
//key : 클립이름 , value : 오디오클립이 들어있는 딕셔너리
private static Dictionary<string, AudioClip> soundDictionary = new Dictionary<string, AudioClip>();
//BGM을 틀어줄 객체
public static AudioSource bgmPlayer; //2D사운드, DDO
public static BGMPlayer bgmPlayerObj; //BGMChange 메서드 때문에 우선 선언 해둠
private float bgmVolume = 1f;
private float effectVolume = 1f;
private float masterVolume = 1f;
// 나중에 UI단에서 조정할 볼륨 값
public float BGMVolume
{
get { return bgmVolume*masterVolume; }
set
{
if (value > 1)
{
bgmVolume = 1;
}
else if (value < 0)
{
bgmVolume = 0;
}
else
{
bgmVolume = value;
}
bgmPlayer.volume = BGMVolume;
}
}
public float EffectVolume
{
get { return effectVolume*masterVolume; }
set
{
if (value > 1)
{
effectVolume = 1;
}
else if (value < 0)
{
effectVolume = 0;
}
else
{
effectVolume = value;
}
}
}
public float MasterVolume
{
get { return masterVolume; }
set
{
if (value > 1)
{
masterVolume = 1;
}
else if (value < 0)
{
masterVolume = 0;
}
else
{
masterVolume = value;
}
bgmPlayer.volume = BGMVolume;
}
}
public static SoundManager Instance //프로퍼티
{
get
{
if (instance == null)
{
instance = new SoundManager(); //주기함수 쓸 수 없으므로 생성자로 초기화
GameObject BGMPlayer = new GameObject("BGMPlayer");
BGMPlayer.AddComponent<AudioSource>();
BGMPlayer.AddComponent<BGMPlayer>();
BGMPlayer.GetComponent<AudioSource>().loop = true;
bgmPlayer = BGMPlayer.GetComponent<AudioSource>();
bgmPlayerObj = BGMPlayer.GetComponent<BGMPlayer>();
}
return instance;
}
}
/// <summary>
/// 효과음 등 짧은 1회용 소리 재생용 매서드입니다.
/// </summary>
/// <param name="tf">호출하는 객체의 트랜스폼이 들어가면 됩니다.</param>
/// <param name="name">원하는 사운드 이름을 적으시면 됩니다. 파일 저장된 이름과 동일합니다.</param>
public async void PlaySound(Transform tf, string SoundName)
{
AudioClip SoundClip;
if (soundDictionary.TryGetValue(SoundName, out SoundClip))
{
GameObject SoundObject = await PoolManager.Pop("AudioPrefab");
SoundPoolObj poolObj = SoundObject.GetComponent<SoundPoolObj>();
poolObj.transform.position = tf.position;
poolObj.PlaySound(SoundClip, EffectVolume);
}
else
{
SoundClip = await ResourcesManager.Instance.GetResource<AudioClip>(SoundName);
GameObject SoundObject = await PoolManager.Pop("AudioPrefab");
SoundPoolObj poolObj = SoundObject.GetComponent<SoundPoolObj>();
poolObj.transform.position = tf.position;
poolObj.PlaySound(SoundClip, EffectVolume);
}
}
public async void PlayBGM(string trackName) //처음에 bgm 틀어줄 객체가 Awake나 Start에서 호출할 함수?
{
AudioClip SoundClip;
if (soundDictionary.TryGetValue(trackName, out SoundClip))
{
bgmPlayer.clip = SoundClip;
bgmPlayer.Play();
}
else
{
SoundClip = await ResourcesManager.Instance.GetResource<AudioClip>(trackName);
bgmPlayer.clip = SoundClip;
bgmPlayer.Play();
}
}
}
======
이 스크립트에서는 이 부분만 사용 GetResource()만 사용.
public class ResourcesManager
{
Dictionary<string, UnityEngine.Object> LoadedDictionary = new Dictionary<string, UnityEngine.Object>();
static ResourcesManager instance;
public static ResourcesManager Instance
{
get
{
if (instance == null)
{
instance = new ResourcesManager();
}
return instance;
}
}
// _key는 mp3파일 이름을 넣으면 됨
public async Task<T> GetResource<T>(string _key, Action _CallbackAction = null) where T : UnityEngine.Object
{
if (LoadedDictionary.ContainsKey(_key))
{
_CallbackAction?.Invoke(); // 콜백이 있다면 호출
return (T)LoadedDictionary[_key]; // 캐시된 리소스 바로 반환
}
else
{
AsyncOperationHandle<T> handle = Addressables.LoadAssetAsync<T>(_key); // Addressables로 로드 시작
await handle.Task; // 로드가 완료될 때까지 기다림 (게임은 멈추지 않음)
if (handle.Status == AsyncOperationStatus.Succeeded) // 로드 성공 시
{
LoadedDictionary.Add(_key, handle.Result); // 로드된 리소스를 딕셔너리에 추가
_CallbackAction?.Invoke(); // 콜백이 있다면 호출
return handle.Result; // 로드된 리소스 반환
}
else // 로드 실패 시
{
Debug.LogError($"NO Exist Asset {_key}"); // 오류 메시지 출력
return null; // null 반환
}
}
}
}
전체적인 사운드 설정 및 재생 흐름:
초기화: 게임이 시작되면 SoundManager.Instance가 처음 호출될 때,
SoundManager가 생성되고 BGMPlayer라는 게임 오브젝트를 만들어서 배경 음악을 재생할 준비.
UI 슬라이더 조작: 플레이어가 BGMOption 스크립트가 붙어있는 UI의 BGM 슬라이더를 조작.
볼륨 값 전달: 슬라이더의 변경된 value는 BGMOption.SetBGMVolume을 통해
SoundManager.Instance.BGMVolume 프로퍼티의 set 접근자로 전달.
볼륨 적용: SoundManager 내부에서 전달받은 값이 0~1 사이로 제한되고, bgmVolume 변수에 저장.
동시에 bgmPlayer.volume을 업데이트하여 실제 게임의 배경 음악 볼륨을 변경.
이 과정에서 마스터 볼륨의 영향도 받음.
사운드 재생 요청: SoundTest 스크립트에서 버튼을 누르거나, 게임 내 다른 스크립트에서 SoundManager.Instance.PlayBGM()
또는 SoundManager.Instance.PlaySound()를 호출.
리소스 로드: SoundManager는 요청받은 사운드 이름이 soundDictionary에 있는지 확인.
없으면 ResourcesManager.Instance.GetResource()를 통해 Addressables 시스템으로부터 해당 오디오 클립을 비동기로 로드.
로드되면 soundDictionary에 추가하여 다음 번 사용을 위해 캐시.
사운드 출력: 로드된 오디오 클립은 bgmPlayer (BGM)나 사운드 풀에서 가져온 SoundPoolObj (효과음)를 통해 실제 소리로 재생.

오른쪽 상단 동그라미들을 설정해줘야한다.
Addressable의 내용을 mp3파일 이름으로 바꿔주고 Group도 현재 있는 폴더로 바꿔줘야 함.

전체 볼륨을 줄이면 BGM이나 SFX의 최대 볼륨이 우측 상단 동그라미친 부분처럼 0.8412843만큼 됨.
슬라이더의 위치만큼 소리의 크기가 적용되는 것을 볼 수 있다. 우측 동그라미 아래에 Test버튼이 있는데
누르면 테스트 음악과 효과음이 나옴. 그걸 들으면서 조절하면 바뀌는지 알 수 있음.