Unity/John Lemon in Nightmareland

Unity Piscine Module06 - 3. 메인 메뉴 만들기

surkim 2024. 8. 21. 17:30

주어진 에셋이 매우 귀여워서 놀랐다.

공포게임인줄 알았는데 캐릭터 디자인만 보면 힐링 게임이다.

 

매니저들이 만들어질 메인메뉴부터 만들기로 했다.

첫인상이 중요하니깐 얼추 꾸며 놓고

GameManager, SoundManager와 메인메뉴 버튼을 관리할 MainMenuManager를 만들고 스크립트를 짰다

GameManager는 아직 특별한게 없다.

SoundManager에서 뻘짓을 조금 했는데

바꾸기전 코드에서는 이전 과제에서 해왔던 것 처럼 SoundManager가 모든 클립과 소스를 다 갖고 다른 오브젝트가 Manager의 함수를 호출하는 방식으로 짰었다 아래는 바꾸기전 코드

using System.Collections;
using System.Collections.Generic;
using System.Data;
using UnityEngine;

public class SoundManager : MonoBehaviour
{
	public static SoundManager instance;

	[SerializeField] private AudioClip SFXBuzzingLight;
	[SerializeField] private AudioClip SFXCandle;
	[SerializeField] private AudioClip SFXFootstepsLooping;
	[SerializeField] private AudioClip SFXGameOver;
	[SerializeField] private AudioClip SFXGhostMove;
	[SerializeField] private AudioClip SFXHouseAmbience;
	[SerializeField] private AudioClip SFXWin;
	private Dictionary<string, AudioSource> audioSources = new Dictionary<string, AudioSource>();


	void Awake()
	{
		if (instance == null)
		{
			instance = this;
			DontDestroyOnLoad(gameObject);
		}
		else if (instance != this)
		{
			Destroy(gameObject);
		}
	}

    void Start()
    {
		AudioSource[] sources = GetComponents<AudioSource>();
		foreach (AudioSource source in sources)
		{
			audioSources.Add(source.clip.name, source);
		}
	}

	public void PlaySound(string clipName)
	{
	    if (audioSources.ContainsKey(clipName))
	    {
		    audioSources[clipName].Play();
		}
    }

	public void SetSoundVolume(string clipName, float volume)
	{
		if (audioSources.ContainsKey(clipName))
		{
			audioSources[clipName].volume = volume;
		}
	}

	public void SettingSFXSoundVolume(float volume)
	{
		foreach (KeyValuePair<string, AudioSource> audioSource in audioSources)
		{
			if (audioSource.Key == SFXHouseAmbience.name)
				continue;
			audioSource.Value.volume = volume;
		}
	}

	public void SettingAmbienceSoundVolume(float volume)
	{
		if (audioSources.ContainsKey(SFXHouseAmbience.name))
		{
			audioSources[SFXHouseAmbience.name].volume = volume;
		}
	}

}

 

열심히 짜다 보니깐 이 게임은 3D이고 소스가 SoundManager에 있으면 소리나는 위치가 항상 동일하게 날 것이고 이러면 부자연스럽다.

대안으로 생각해낸게 모든 사운드 소스를 분산시키는 거고 그럼 SoundManager에서 volume setting을 할 수 없게 된다.

 

검색을 하여 AudioMixer를 도입해 해결했다.

원래는 Audio source -> Listener 흐름이라면 Audio source -> Mixer -> Listener 로 중간다리를 놓는 것

출처: https://docs.unity3d.com/kr/2020.3/Manual/AudioMixerOverview.html

오브젝트에 소스를 넣고 output설정을 Mixer로 놓으면 Mixer만 설정하면 볼륨조절 뿐만 아니라 사운드 관련 설정들을 한방에 관리할 수가 있었다.

그래서 바뀐 코드

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using UnityEngine;
using UnityEngine.Audio;

public class SoundManager : MonoBehaviour
{
	public static SoundManager instance;

	[SerializeField] private AudioMixer	audioMixer;

	void Awake()
	{
		if (instance == null)
		{
			instance = this;
			DontDestroyOnLoad(gameObject);
		}
		else if (instance != this)
		{
			Destroy(gameObject);
		}
	}

	void Start()
	{
		SetBGMVolume(PlayerPrefs.GetFloat("BGMVolume", 0));
		SetSFXVolume(PlayerPrefs.GetFloat("SFXVolume", 0));
	}

	public void SetSFXVolume(float volume)
	{
		if (volume <= 0.0001f)
			audioMixer.SetFloat("SFX", -80);
		else
			audioMixer.SetFloat("SFX", Mathf.Log10(volume) * 20);
	}

	public void SetBGMVolume(float volume)
	{
		if (volume <= 0.0001f)
			audioMixer.SetFloat("BGM", -80);
		else
			audioMixer.SetFloat("BGM", Mathf.Log10(volume) * 20);
	}
}

 

AudioMixer의 볼륨은 단위가 dB이라서 볼륨 조정할 Slider의 float (0, 1) 과 달라 계산식을 넣어주었고

volume == 0 이면 계산식이 -Infinite가 되어  볼륨이 다시 커지는 버그를 발견하여 0되기 전에 볼륨을 꺼주었다.

확실히 코드가 깔끔해지고 사운드 추가할때마다 SoundManager에 넣어주고 소스 만들고 하는 것보다 훨씬 좋다

 

 

지금까지 결과물

0

 

 

정리하다보니 SoundManager보다 AudioManager가 좋을거 같아서 변경!

이제 플레이어 이동 구현 해야지