- 주제 : 사운드 관리 매니저 생성 및 활용
>> 오브젝트 풀[ObjectPool]
(오브젝트를 미리 생성하여 큐에 넣어 놓고 필요할 때마다 가져다 사용)
>> 게임매니저[GameManager]
(오브젝트 풀 초기화 및 관리)
>> 사운드매니저[SoundManager]
(배경음악 및 효과음 관리)
>> 사운드소스[SoundSource]
(효과음을 재생하는 오디오 소스 관리)
>> 특정 상황 시 효과음 재생
- 공부내용
1. 오브젝트 풀
: Object Pooling은 몬스터나 총알, 효과음 등 게임화면에서 나타났다가 사라졌다를 반복하는 요소들을
비활성화상태(안 보이는 상태)로 미리 생성해 놓고, 필요할 때마다 활성화시키는 기법이다.
이 기법을 사용하면, 생성과 삭제를 반복하지 않기 때문에 메모리를 아낄 수 있다.
[System.Serializable]
:클래스별 카테고리화
(다양한 종류의 데이터들을 인스펙터 창에서 추가 혹은 삭제 가능)
ObjectPool.cs
using System.Collections.Generic;
using UnityEngine;
public class ObjectPool : MonoBehaviour
{
// 오브젝트 풀 데이터를 정의할 데이터 모음 정의
[System.Serializable]
public class Pool
{
public string tag; // 태그
public GameObject prefab; // 프리팹
public int size; // 크기
}
public List<Pool> Pools; // 풀 목록
public Dictionary<string, Queue<GameObject>> PoolDictionary; // 풀 딕셔너리
private void Awake()
{
// 오브젝트 풀 생성
PoolDictionary = new Dictionary<string, Queue<GameObject>>();
foreach (var pool in Pools)
{
Queue<GameObject> objectPool = new Queue<GameObject>();
for (int i = 0; i < pool.size; i++)
{
GameObject obj = Instantiate(pool.prefab);
obj.SetActive(false); // 비활성화
objectPool.Enqueue(obj); // 큐에 추가
}
PoolDictionary.Add(pool.tag, objectPool); // 딕셔너리에 추가
}
}
public GameObject SpawnFromPool(string tag)
{
// 해당 태그의 풀 존재 확인
if (!PoolDictionary.ContainsKey(tag))
return null;
// 오브젝트 풀에서 오브젝트 가져오기
GameObject obj = PoolDictionary[tag].Dequeue();
PoolDictionary[tag].Enqueue(obj);
obj.SetActive(true); // 활성화
return obj;
}
}
2. 게임매니저
: 게임의 전반적인 상태를 관리하고, 스크립트 간 필요한 요소들을 이어주는 역할을 한다.
GameManager 오브젝트 생성 -> GameManager 스크립트 할당 -> ObjectPool 스크립트 할당
GameManager.cs
using UnityEngine;
public class GameManager : MonoBehaviour
{
public static GameManager Instance; // 싱글톤 인스턴스
public ObjectPool ObjectPool { get; private set; } // 오브젝트 풀
private void Awake()
{
Instance = this; // 싱글톤 설정
ObjectPool = GetComponent<ObjectPool>(); // 오브젝트 풀 가져오기
}
}
3. 사운드매니저
음악을 재생하는 메서드를 작성할 때는, 가장 먼저 음악을 정지해주고, 이후 음악을 재생하는 코드를 넣는 것이 좋다.
// 배경음악 변경 메서드
public static void ChangeBackGroundMusic(AudioClip music)
{
instance.musicAudioSource.Stop(); // 음악 정지
instance.musicAudioSource.clip = music; // 새로운 음악 클립 설정
instance.musicAudioSource.Play(); // 음악 재생
}
(사운드들이 서로 꼬이는 것을 방지)
SoundManager.cs
using UnityEngine;
public class SoundManager : MonoBehaviour
{
public static SoundManager instance; // 싱글톤 인스턴스
[SerializeField][Range(0f, 1f)] private float soundEffectVolume; // 효과음 볼륨
[SerializeField][Range(0f, 1f)] private float soundEffectPitchVariance; // 효과음 피치 변동
[SerializeField][Range(0f, 1f)] private float musicVolume; // 음악 볼륨
private AudioSource musicAudioSource; // 음악 오디오 소스
public AudioClip musicClip; // 음악 클립
private void Awake()
{
instance = this; // 싱글톤 설정
musicAudioSource = GetComponent<AudioSource>(); // 오디오 소스 가져오기
musicAudioSource.volume = musicVolume; // 볼륨 설정
musicAudioSource.loop = true; // 반복 재생 설정
}
private void Start()
{
ChangeBackGroundMusic(musicClip); // 배경음악 변경
}
public static void ChangeBackGroundMusic(AudioClip music)
{
instance.musicAudioSource.Stop(); // 음악 정지
instance.musicAudioSource.clip = music; // 새로운 음악 클립 설정
instance.musicAudioSource.Play(); // 음악 재생
}
public static void PlayClip(AudioClip clip)
{
// 오브젝트 풀에서 사운드 소스 가져오기
GameObject obj = GameManager.Instance.ObjectPool.SpawnFromPool("SoundSource");
obj.SetActive(true); // 활성화
SoundSource soundSource = obj.GetComponent<SoundSource>();
soundSource.Play(clip, instance.soundEffectVolume, instance.soundEffectPitchVariance); // 재생
}
}
4. 사운드소스
SoundSource 오브젝트 생성 -> AudioSource 컴포넌트 추가 -> SoundSource 스크립트 추가 -> 오브젝트 프리팹화
SoundSource.cs
using UnityEngine;
public class SoundSource : MonoBehaviour
{
private AudioSource audioSource; // 오디오 소스
public void Play(AudioClip clip, float soundEffectVolume, float soundEffectPitchVariance)
{
if (audioSource == null)
audioSource = GetComponent<AudioSource>();
CancelInvoke(); // 기존 호출 취소
audioSource.clip = clip; // 클립 설정
audioSource.volume = soundEffectVolume; // 볼륨 설정
audioSource.Play(); // 재생
audioSource.pitch = 1f + Random.Range(-soundEffectPitchVariance, soundEffectPitchVariance); // 피치 설정
Invoke("Disable", clip.length + 2); // 재생 종료 후 비활성화 호출 예약
}
public void Disable()
{
audioSource.Stop(); // 재생 중지
gameObject.SetActive(false); // 비활성화
}
}
5. 특정 상황 시 효과음 재생
클립이 존재하면 효과음을 재생하는 코드를 추가
(클립이 없더라도 null의 상황이 발생하지 않음)
[SerializeField] private AudioClip ShootingClip; // 발사 클립
...
if (ShootingClip) SoundManager.PlayClip(ShootingClip); // 효과음 재생
...
'🌐 유니티 (Unity)' 카테고리의 다른 글
Day 41 - WebGL로 웹 새로고침 시 게임 상태 저장하기 (1) | 2024.12.05 |
---|---|
Day 40 - 상태머신(3D 방치형 게임 만들기 中) (0) | 2024.06.18 |
Day 38 - SaveManager.cs 생성(정보 저장) (2) | 2024.06.11 |
Day 37 - 3D 건축 시스템 (1) | 2024.06.04 |
Day 36 - AI 네비게이션 (1) | 2024.06.03 |