Abstract
Sound Manager ๋ AudioSource ๋ฅผ ์ง์ ๋ค๊ณ ๋ค๋์ง ์๊ฒ ํด ์ฃผ๋ ๋ชจ๋์
๋๋ค. "์ด ์ฃผ์์ ์๋ฆฌ๋ฅผ, ์ด ๊ทธ๋ฃน์ผ๋ก, ์ฌ๊ธฐ์ ํ์ด ์ค" ํ ์ค์ด๋ฉด ํด๋ฆฝ ๋ก๋ยท๋น AudioSource ์ฐพ๊ธฐยท์ฌ์ยท๋๋ ๋ค ์ ๋ฆฌ๋ฅผ ๋์ ํฉ๋๋ค. ํต์ฌ ๊ฐ๋
์ ๋ โ ๊ทธ๋ฃน(๋ณผ๋ฅจ์ ํจ๊ป ์กฐ์ ํ๋ ๋ฌถ์)๊ณผ ์์ด์ ํธ(๊ทธ ๊ทธ๋ฃน์ด ๋์์ ๋ผ ์ ์๋ ์๋ฆฌ์ ์)์
๋๋ค.
Unity ๊ธฐ๋ณธ ๋ฐฉ์๊ณผ ๋น๊ต
ํ๊ณ ์ถ์ ์ผ | Unity ๊ธฐ๋ณธ | Sound Manager |
ํจ๊ณผ์ ํ ๋ฒ | ์ค๋ธ์ ํธ๋ง๋ค AudioSource โข ํด๋ฆฝ ์ฐธ์กฐ + PlayOneShot | PlaySound("PlayerHurt", "Soundeffects", position) |
ํจ๊ณผ์ ๋ณผ๋ฅจ ์ผ๊ด ์กฐ์ | ๋ชจ๋ AudioSource ๋ฅผ ์ฐพ์ ๋๊ฑฐ๋ ๋ฏน์ ๊ตฌ์ฑ | ๊ทธ๋ฃน์ Volume ํ๋ |
๋์ ์ฌ์ ์ ์ ํ | ์ง์ ๊ตฌํ | ๊ทธ๋ฃน์ ์์ด์ ํธ ์ + ์ฐ์ ์์ |
๋ฐฐ๊ฒฝ์ ํ์ด๋ ์ ํ | ์ฝ๋ฃจํด์ผ๋ก ๋ณผ๋ฅจ ๋ณด๊ฐ | FadeInSeconds, StopSound(id, fadeOutSeconds) |
์ฌ์ ํฉ์ด์ง ํด๋ฆฝ ์ฐธ์กฐ | ํ๋ฆฌํน๋ง๋ค ์ธ์คํํฐ์ ์ฐ๊ฒฐ | ์ฃผ์ ๋ฌธ์์ด๋ง. ํด๋ฆฝ์ ํ์ํ ๋ ๋ก๋ |
ToyboxNightmare ์์์ ์ค์ ์ฌ์ฉ
ํจ๊ณผ์ ์ฌ์์ ํ ํจ์๋ก ๋ชจ์์ต๋๋ค.
public static class GameSound
{
public static void PlaySfx(string assetName, Vector3 worldPosition)
{
if (string.IsNullOrEmpty(assetName)) return;
SoundComponent sound = GameEntry.GetComponent<SoundComponent>();
if (sound == null) return;
sound.PlaySound(assetName, SoundTable.SfxGroup, worldPosition);
}
}
// ์ฐ๋ ์ชฝ
GameSound.PlaySfx("ZomBunnyDeath", transform.position);
C#
๋ณต์ฌ
"์๋ฆฌ๊ฐ ์ ๋๋ ๊ฒ์ด ๊ฒ์์ ๋ฉ์ถ ์ด์ ๋ ๋์ง ์๋๋ค"๋ ์์น์ผ๋ก, ์ฃผ์๊ฐ ๋น์๊ฑฐ๋ ์ฌ์ด๋ ์์คํ
์ด ์์ผ๋ฉด ์กฐ์ฉํ ๋์ด๊ฐ๋๋ค.
๊ทธ๋ฃน | ์์ด์ ํธ ์ | ์ฉ๋ |
Music | 1 | ๋ฐฐ๊ฒฝ์ (ํ ๋ฒ์ ํ ๊ณก) |
Soundeffects | 8 | ํผ๊ฒฉยท์ฌ๋ง ํจ๊ณผ์. ๋์์ 8๊ฐ๊น์ง ๊ฒน์น๋ค |
์์ ๊ฐ ๋ชจ๋ ์๋ฆฌ๋ฅผ Sound Manager ๋ก ๋ณด๋ด๋ ๊ฒ์ ์๋๋๋ค. ๋ฒ๊ฐ ๋ฐ์ฌ์์ด๋ ์ฐฉํ์์ฒ๋ผ ์ดํํธ ํ๋ฆฌํน์ ์ด๋ฏธ AudioSource ๋ก ๋ค์ด ์๋ ์๋ฆฌ๋ ๊ทธ๋๋ก ๋ก๋๋ค. ํํฐํด๊ณผ ํ ๋ฉ์ด๋ฆฌ๋ก ๋ง๋ค์ด์ง ์ฐ์ถ์ด๋ผ ๋ผ์ด ๋ด๋ฉด ํ๋ฆฌํน ๋จ์๋ก ์กฐ์ ํ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค. Sound Manager ๋ฅผ ๊ฑฐ์น๋ ๊ฒ์ ํ๋ฆฌํน์ ์๋ ๊ฒ์ํ๋ ์ด ์ฌ์ด๋(ํผ๊ฒฉ, ์ฌ๋ง)์
๋๋ค. "์ ๋ถ ํ๋ ์์ํฌ๋ก"๊ฐ ์๋๋ผ ๊ฒฝ๊ณ๋ฅผ ์ ํ๋ ๊ฒ์ด ์ค๋ฌด์
๋๋ค.
์์ด์ ํธ๊ฐ ๋ค ์ฐผ์ ๋
8๊ฐ๊ฐ ๋ชจ๋ ์ฌ์ ์ค์ธ๋ฐ 9๋ฒ์งธ ์๋ฆฌ๊ฐ ์ค๋ฉด:
โข
์ ์๋ฆฌ์ ์ฐ์ ์์๊ฐ ๋ ๋์ผ๋ฉด ๊ฐ์ฅ ์ฐ์ ์์ ๋ฎ์ ์๋ฆฌ๋ฅผ ๋๊ณ ๊ทธ ์๋ฆฌ์์ ์ฌ์ํ๋ค
โข
๊ฐ์ผ๋ฉด ๊ฐ์ฅ ์ค๋๋ ์๋ฆฌ๋ฅผ ๋๋๋ค (๊ทธ๋ฃน์ Avoid Being Replaced By Same Priority ๊ฐ ์ผ์ ธ ์์ผ๋ฉด ๋์ง ์๊ณ ์ ์๋ฆฌ๋ฅผ ๋ฒ๋ฆฐ๋ค)
โข
๋ฎ์ผ๋ฉด ์ ์๋ฆฌ๋ฅผ ๋ฒ๋ฆฌ๊ณ PlaySoundFailure ์ด๋ฒคํธ๊ฐ ์จ๋ค
ํ๋ง ๊ฒ์์ฒ๋ผ ํจ๊ณผ์์ด ์์์ง๋ ์ฅ๋ฅด์์๋ "ํ๋ ์ด์ด ํผ๊ฒฉ์" ๊ฐ์ ์ค์ํ ์๋ฆฌ์ ๋์ ์ฐ์ ์์๋ฅผ ์ค์ ๋ฌปํ์ง ์๊ฒ ํฉ๋๋ค.
ํ์ฅ โ ๋ฐฐ๊ฒฝ์ ๋ฃ๊ธฐ
private const float MusicFadeSeconds = 2f;
PlaySoundParams musicParams = PlaySoundParams.Create();
musicParams.Loop = true;
musicParams.FadeInSeconds = MusicFadeSeconds;
mMusicId = sound.PlaySound("BattleTheme", SoundTable.MusicGroup, musicParams);
// ๊ณก์ ๋ฐ๊ฟ ๋
sound.StopSound(mMusicId, MusicFadeSeconds);
C#
๋ณต์ฌ
์ํฐํฐ์ ๋ถ์ด ๋ฐ๋ผ๋ค๋๋ ์๋ฆฌ(์์ง์, ๋ฐ์๋ฆฌ)๋ PlaySound(asset, group, bindingEntity) ๋ฅผ ์๋๋ค. ์ํฐํฐ๊ฐ ์์ง์ด๋ฉด ์๋ฆฌ ์์น๋ ๋ฐ๋ผ๊ฐ๊ณ , ์ํฐํฐ๊ฐ ํ์๋๋ฉด ์๋ฆฌ๋ ํจ๊ป ๋ฉ์ต๋๋ค.
์ด ์๋์
์์ ๋ค๋ฅธ ์ ยท ๋ณธ๋ฌธ์ ์ฝ์ ๋ ์ฃผ์ํ ์
โข
๋ณธ๋ฌธ "์ฌ์ฉ ๋ฐฉ๋ฒ 1~3"์ ์ด๊ธฐํยท๊ทธ๋ฃน ์์ฑยท์์ด์ ํธ ์ถ๊ฐ ์ฝ๋๋ ์ฝ์ด API ๋ฅผ ์ง์ ๋ถ๋ฅด๋ ์์์
๋๋ค. ์ค์ ๋ก๋ SoundComponent ๊ฐ ์ธ์คํํฐ ์ค์ (๊ทธ๋ฃน ์ด๋ฆ, ์์ด์ ํธ ์)์ ์ฝ์ด Start ์์ ์ ๋ถ ํด ์ค๋๋ค. ๊ฒ์ ์ฝ๋๋ PlaySound ๋ถํฐ ์๋๋ค.
โข
์์
์ด๋ฆ ์๋ฆฌ์ ํ์ผ๋ช
("explosion.wav")์ด ์๋๋ผ Addressables ์ฃผ์("PlayerHurt")๋ฅผ ๋ฃ์ต๋๋ค.
โข
๊ฒฐ๊ณผ๋ soundManager.PlaySoundSuccess += ๊ฐ ์๋๋ผ EventComponent ์ PlaySoundSuccessEventArgs / PlaySoundFailureEventArgs ๊ตฌ๋
์ผ๋ก ๋ฐ์ต๋๋ค. PlaySoundUpdate / PlaySoundDependencyAsset ์ ์ด ์๋์
์์ ๋ฐ์ํ์ง ์์ต๋๋ค.
โข
๊ทธ๋ฃน ๋ณผ๋ฅจ๊ณผ AudioMixer ๋ ๋ณ๊ฐ์
๋๋ค. ์์ ์ ๋ณผ๋ฅจ ์ฌ๋ผ์ด๋๋ ๊ทธ๋ฃน์ Volume ์ด ์๋๋ผ AudioMixer ์ ๋
ธ์ถ ํ๋ผ๋ฏธํฐ๋ฅผ ์ง์ ์กฐ์ ํฉ๋๋ค(์๋ณธ Zombie Toys ์ ๊ตฌ์ฑ์ ๋ฐ๋ฆ). ๋ฏน์๋ฅผ ์ฐ์ง ์๋ ํ๋ก์ ํธ๋ผ๋ฉด sound.GetSoundGroup("Soundeffects").Volume = 0.5f ํ ์ค์ด ๊ฐ์ฅ ๊ฐ๋จํฉ๋๋ค.
โข
์๋ฆฌ๋ง๋ค ํด๋ฆฝ์ ๊ทธ๋๊ทธ๋ ๋ก๋ํฉ๋๋ค. ์ฒ์ ์ฌ์ํ ๋ ํ ๋ฐ์ ๋ฆ์ ์ ์์ผ๋ฏ๋ก, ๋ ์ฌ์์ด ๋๋๋ฉด ํด๋ฆฝ์ ๋ฐ๋ฉํ๋ฏ๋ก, ์์ฃผ ์ฐ๋ ํจ๊ณผ์์ ๋ก๋ฉ ํ๋ฉด์์ ResourceComponent.LoadAsset ์ผ๋ก ๋ฏธ๋ฆฌ ํ ๋ฒ ๋ก๋ํด ์ฝ๋ฐฑ์ผ๋ก ๋ฐ์ ์์
์ ์ฅ๊ณ ์์ผ๋ฉด(ํ์ด ๋๋ ๋ UnloadAsset) ํด๋ฆฝ์ด ๋ฉ๋ชจ๋ฆฌ์ ๋จ์ ์ดํ ์ฌ์์ ์ง์ฐ์ด ์์ต๋๋ค.
โข
Unity 6 ์์ ์๋ฆฌ๋ฅผ ์ฌ์ํ ๋๋ง๋ค ์ฝ์์ Attempting to set 'time' on an audio source that has a resource assigned that is not a clip is ignored! ๊ฒฝ๊ณ ๊ฐ ์ฐํ๋ ๋ฌธ์ ๊ฐ ์์์ ์์์ต๋๋ค(์์ด์ ํธ๋ฅผ ์ด๊ธฐํํ๋ฉด์ ํด๋ฆฝ์ด ์๋ AudioSource ์ time ์ 0 ์ผ๋ก ๋๋๋ฆฌ๊ธฐ ๋๋ฌธ). ์ด ์๋์
์์๋ ๊ณ ์ณ ๋์ด ๋ ์ด์ ๋์ค์ง ์์ต๋๋ค.
Sound Manager ๊ฐ์
Sound Manager๋ ๊ฒ์์์ ์ค๋์ค ๋ฆฌ์์ค๋ฅผ ๊ด๋ฆฌยท๋ก๋ยท์ฌ์ํ๋ ํต์ฌ ๋ชจ๋์
๋๋ค.
๋ค์๊ณผ ๊ฐ์ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค:
โข
์ฌ์ด๋๋ฅผ ๋
ผ๋ฆฌ์ ์ธ ๊ทธ๋ฃน์ผ๋ก ๊ด๋ฆฌ
โข
์ฌ์ ์ ์ด(์ฌ์, ์ ์ง, ์ผ์ ์ ์ง, ์ฌ๊ฐ)
โข
๊ทธ๋ฃน ๋ฐ ๊ฐ๋ณ ์ฌ์ด๋ ์์ค์์ ๋ณผ๋ฅจยท์์๊ฑฐ ์ ์ด
โข
์ฌ์ ์ฐ์ ์์ ์ค์ ๋ฐ ์ ํ ์ ๋์ ์ ์
โข
ํ์ด๋ ์ธยท์์ ์ง์
โข
๋น๋๊ธฐ ์ฌ์ด๋ ๋ก๋ฉ๊ณผ ์ด๋ฒคํธ ์๋ฆผ
์ํคํ ์ฒ
โข
Game Framework ์ ์ฒด์์ ์ฌ์ฉํ๋ ๋ชจ๋ ์ํคํ
์ฒ ํจํด์ ๋ฐ๋ฆ
๋๋ค.
โข
GameFrameworkModule์ ์์๋ฐ๊ณ GameFrameworkEntry์ ์ํด ๊ด๋ฆฌ๋ฉ๋๋ค.
โข
์ฌ์ด๋ ๋ฆฌ์์ค ๋ก๋๋ Resource Manager์ ์์กดํฉ๋๋ค.
โข
ํ๋ซํผ๋ณ ๊ตฌํ์ Helper ์ธํฐํ์ด์ค๋ก ์ถ์ํ๋ฉ๋๋ค.
ํต์ฌ ๊ตฌ์ฑ ์์
1. Sound Group
์ฌ์ด๋๋ฅผ ๊ทธ๋ฃน๋ณ๋ก ๋ฌถ์ด ์ ์ดํฉ๋๋ค.
โข
Name: ๊ทธ๋ฃน์ ๊ณ ์ ์ด๋ฆ
โข
AvoidBeingReplacedBySamePriority: ๋์ผ ์ฐ์ ์์ ์ฌ์ด๋๋ก ๋์ฒด ์ฌ๋ถ
โข
Mute: ๊ทธ๋ฃน ์ ์ฒด ์์๊ฑฐ ์ฌ๋ถ
โข
Volume: ๊ทธ๋ฃน ์ ์ฒด ๋ณผ๋ฅจ(0.0~1.0)
โข
SoundAgentCount: ํด๋น ๊ทธ๋ฃน์ ์ฌ์ด๋ ์์ด์ ํธ ์
2. Sound Agent
โข
์ค์ ์ฌ์ด๋ ์ฌ์์ ๋ด๋นํฉ๋๋ค.
โข
๊ฐ ๊ทธ๋ฃน์ ์ฌ๋ฌ Sound Agent๋ฅผ ๊ฐ์ง ์ ์์ผ๋ฉฐ, ์ด๋ ๋์์ ์ฌ์ ๊ฐ๋ฅํ ์ฌ์ด๋ ์๋ฅผ ์๋ฏธํฉ๋๋ค.
โข
ํ๋ซํผ๋ณ Agent Helper๋ฅผ ํตํด ์์ฑ๋ฉ๋๋ค.
์ฌ์ฉ ๋ฐฉ๋ฒ
1. ์ด๊ธฐํ
ISoundManager soundManager = GameFrameworkEntry.GetModule<ISoundManager>();
soundManager.SetResourceManager(resourceManager);
soundManager.SetSoundHelper(soundHelper);
C#
๋ณต์ฌ
2. ์ฌ์ด๋ ๊ทธ๋ฃน ์์ฑ
soundManager.AddSoundGroup("Music", musicGroupHelper);
soundManager.AddSoundGroup("SFX", true, false, 0.8f, sfxGroupHelper);
C#
๋ณต์ฌ
3. ์ฌ์ด๋ ์์ด์ ํธ ์ถ๊ฐ
soundManager.AddSoundAgentHelper("Music", musicAgentHelper);
for (int i = 0; i < 10; i++)
{
soundManager.AddSoundAgentHelper("SFX", CreateSoundAgentHelper());
}
C#
๋ณต์ฌ
4. ์ฌ์ด๋ ์ฌ์
// ๊ธฐ๋ณธ ์ฌ์
int serialId = soundManager.PlaySound("explosion.wav", "SFX");
// ํ๋ผ๋ฏธํฐ ์ฌ์ฉ
PlaySoundParams playSoundParams = PlaySoundParams.Create();
playSoundParams.Priority = 100;
playSoundParams.Loop = true;
playSoundParams.VolumeInSoundGroup = 0.5f;
playSoundParams.FadeInSeconds = 2f;
playSoundParams.SpatialBlend = 1f;
int musicId = soundManager.PlaySound("background.mp3", "Music", playSoundParams);
C#
๋ณต์ฌ
5. ์ฌ์ ์ ์ด
soundManager.StopSound(serialId);
soundManager.StopSound(serialId, 3.0f);
soundManager.PauseSound(serialId);
soundManager.ResumeSound(serialId);
soundManager.StopAllLoadedSounds();
C#
๋ณต์ฌ
์ด๋ฒคํธ ์์คํ
โข
PlaySoundSuccess โ ์ฌ์ด๋๊ฐ ์ ์์ ์ผ๋ก ์ฌ์ ์์
โข
PlaySoundFailure โ ๋ก๋ ๋๋ ์ฌ์ ์คํจ
โข
PlaySoundUpdate โ ๋ก๋ฉ ์งํ๋ฅ ์
๋ฐ์ดํธ
โข
PlaySoundDependencyAsset โ ์ฌ์ด๋ ์ข
์ ๋ฆฌ์์ค ๋ก๋ ์ ํธ์ถ
// ์ฝ์ด ๋ด๋ถ์์๋ C# ์ด๋ฒคํธ๋ก ๋๊ฐ์ง๋ง (์๋), ๊ฒ์ ์ฝ๋์์๋ EventComponent ๋ก ๋ฐ๋๋ค
soundManager.PlaySoundSuccess += (sender, e) =>
{
Debug.Log($"Sound {e.SerialId} ({e.SoundAssetName}) started!");
};
// ๊ฒ์ ์ฝ๋
events.Subscribe(PlaySoundSuccessEventArgs.EventId, OnPlaySoundSuccess);
events.Subscribe(PlaySoundFailureEventArgs.EventId, OnPlaySoundFailure);
C#
๋ณต์ฌ
๋ฆฌ์์ค ์์คํ ์ฐ๋
โข
Sound Manager๋ ์ฌ์ด๋ ์ฌ์ ์์ฒญ ์ Resource Manager๋ฅผ ํตํด ๋ฆฌ์์ค๋ฅผ ๋ก๋ํฉ๋๋ค.
โข
๋ก๋ ์๋ฃ ํ Sound Agent๋ฅผ ์์ฑํด ์ฌ์์ ์์ํฉ๋๋ค.
ํ๋ ์์ํฌ ๋ด ์์น
โข
Sound Manager๋ Entity Manager, UI Manager์ ํจ๊ป ํต์ฌ ๋ชจ๋์
๋๋ค.
โข
์ธ ๋ชจ๋ ๋ชจ๋ Resource Manager์ ์์กดํ๋ฉฐ, ๊ทธ๋ฃน ๊ธฐ๋ฐ ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
์ผ๋ฐ ์ฌ์ฉ ์ฌ๋ก
๋ฐฐ๊ฒฝ์์
soundManager.AddSoundGroup("Music", false, false, 0.8f, musicGroupHelper);
soundManager.AddSoundAgentHelper("Music", musicAgentHelper);
PlaySoundParams musicParams = PlaySoundParams.Create();
musicParams.Loop = true;
musicParams.FadeInSeconds = 2.0f;
int musicId = soundManager.PlaySound("background.mp3", "Music", musicParams);
C#
๋ณต์ฌ
ํจ๊ณผ์
soundManager.AddSoundGroup("SFX", true, false, 1.0f, sfxGroupHelper);
for (int i = 0; i < 5; i++)
{
soundManager.AddSoundAgentHelper("SFX", CreateSfxAgentHelper());
}
soundManager.PlaySound("explosion.wav", "SFX");
soundManager.PlaySound("footstep.wav", "SFX");
C#
๋ณต์ฌ
UI ์ฌ์ด๋
soundManager.AddSoundGroup("UI", false, false, 0.5f, uiSoundGroupHelper);
soundManager.AddSoundAgentHelper("UI", uiSoundAgentHelper);
soundManager.PlaySound("button_click.wav", "UI");
soundManager.PlaySound("menu_open.wav", "UI");
C#
๋ณต์ฌ
๊ฒฐ๋ก
Game Framework์ Sound Manager๋ ๊ทธ๋ฃนยท์์ด์ ํธ ๊ธฐ๋ฐ ์ค๋์ค ์์คํ
์ ์ ๊ณตํด, ์ธ๋ฐํ ์ฌ์ด๋ ์ ์ด์ ๋ฆฌ์์ค ๊ด๋ฆฌ ํตํฉ์ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค. ์ด๋ฅผ ํตํด ๋ค์ํ ์ค๋์ค ํ๊ฒฝ์์ ์ ์ฐํ๊ณ ๊ฐ๋ ฅํ ์ฌ์ ๊ธฐ๋ฅ์ ๊ตฌํํ ์ ์์ต๋๋ค.









