금일은 https://github.com/MathewHDYT/Unity-Audio-Manager 이 오픈소스를 뜯어보면서 주석을 한글화하고, 어떤 기능들을 제공하는지 확인해보는 시간을 가져보겠습니다.
주요 구성 요소
1. IAudioManager 인터페이스
IAudioManager 는 오디오 관리의 핵심 인터페이스로, 다양한 오디오 작업을 수행할 수 있는 메서드를 정의하고 있습니다. 이 인터페이스는 사운드 추가, 재생, 일시 정지, 제거 등의 기능을 제공합니다.
또한, 오디오 믹서 그룹과의 상호작용을 위한 메서드도 포함되어 있습니다.
public interface IAudioManager
{
/// <summary>
/// 주어진 설정으로 2D 사운드를 재생 가능한 사운드에 추가하고,
/// 아직 생성되지 않은 경우 주어진 설정으로 새 AudioSource 객체를 생성하여
/// 생성자에서 이 클래스에 전달된 GameObject에 추가합니다.
/// 3D 기능을 추가하려면 Set3DAudioOptions 메서드를 추가로 호출하세요.
/// </summary>
/// <param name="name">새로운 사운드의 이름입니다.</param>
/// <param name="audioPath">Resource 폴더 내에서 추가하고자 하는 클립의 경로입니다.</param>
/// <param name="volume">새로운 사운드의 볼륨입니다.</param>
/// <param name="pitch">새로운 사운드의 피치입니다.</param>
/// <param name="loop">사운드 재생 완료 후 반복 여부를 결정합니다.</param>
/// <param name="source">새로운 사운드에 추가할 AudioSource입니다.</param>
/// <param name="mixerGroup">사운드가 영향을 받을 AudioMixerGroup입니다.</param>
/// <returns>주어진 경로와 설정으로 2D 사운드를 추가하는 데 실패한 경우와 그 방법을 나타내는 AudioError입니다.</returns>
public AudioError AddSoundFromPath(string name, string audioPath, float volume = Constants.DEFAULT_VOLUME, float pitch = Constants.DEFAULT_PITCH, bool loop = Constants.DEFAULT_LOOP, AudioSource source = Constants.DEFAULT_SOURCE, AudioMixerGroup mixerGroup = Constants.DEFAULT_GROUP);
/// <summary>
/// 모든 등록된 사운드 이름의 기본 목록에 대한 열거자를 반환합니다.
/// LerpVolume과 같은 메서드를 각 등록된 사운드에 대해 호출하는 데 사용할 수 있습니다.
/// </summary>
/// <returns>모든 등록된 사운드 이름에 대한 열거자입니다.</returns>
public IEnumerable<string> GetEnumerator();
/// <summary>
/// 주어진 ChildType으로 사운드를 재생합니다.
/// </summary>
/// <param name="name">등록된 사운드의 이름입니다.</param>
/// <param name="child">메서드를 호출할 자식 객체입니다.</param>
/// <returns>사운드 재생 실패 여부와 실패 원인을 나타내는 AudioError입니다.</returns>
public AudioError Play(string name, ChildType child = Constants.DEFAULT_CHILD_TYPE);
/// <summary>
/// 주어진 시작 시간부터 주어진 ChildType으로 사운드를 재생합니다.
/// </summary>
/// <param name="name">등록된 사운드의 이름입니다.</param>
/// <param name="startTime">재생 시작 시간(초)입니다.</param>
/// <param name="child">메서드를 호출할 자식 객체입니다.</param>
/// <returns>지정된 시작 시간부터 사운드를 재생하는 데 실패한 경우와 그 원인을 나타내는 AudioError입니다.</returns>
public AudioError PlayAtTimeStamp(string name, float startTime, ChildType child = Constants.DEFAULT_CHILD_TYPE);
/// <summary>
/// 주어진 사운드와 ChildType의 현재 재생 위치를 초 단위로 가져옵니다.
/// </summary>
/// <param name="name">등록된 사운드의 이름입니다.</param>
/// <param name="time">재생 위치(초)가 복사될 변수입니다. 실패 시 <see cref="float.NaN"/>이 저장됩니다.</param>
/// <param name="child">메서드를 호출할 자식 객체입니다.</param>
/// <returns>현재 재생 위치를 가져오는 데 실패한 경우와 그 원인을 나타내는 AudioError입니다.</returns>
public AudioError GetPlaybackPosition(string name, out float time, ChildType child = Constants.DEFAULT_CHILD_TYPE);
/// <summary>
/// 주어진 ChildType을 가진 노래가 재생되어야 하는 방향을 설정합니다.
/// 0 이상의 피치는 일반적인 재생이며, 주어진 피치 값으로 시작부터 재생됩니다.
/// 0 미만은 노래가 끝에서부터 역방향으로 재생됨을 의미합니다.
/// </summary>
/// <param name="name">등록된 사운드의 이름입니다.</param>
/// <param name="pitch">재생 방향과 속도를 나타내는 피치입니다. (0 이상: 정방향, 0 미만: 역방향)</param>
/// <param name="child">메서드를 호출할 자식 객체입니다.</param>
/// <returns>재생 방향 설정 실패 여부와 그 원인을 나타내는 AudioError입니다.</returns>
public AudioError SetPlaybackDirection(string name, float pitch = Constants.DEFAULT_REVERSE_PITCH, ChildType child = Constants.DEFAULT_CHILD_TYPE);
/// <summary>
/// 3D 공간의 위치에 새로운 자식 사운드를 등록하여 나중에 해당 ChildType 값으로 참조할 수 있게 합니다.
/// </summary>
/// <param name="name">등록된 사운드의 이름입니다.</param>
/// <param name="position">새 자식 사운드를 생성할 3D 위치입니다.</param>
/// <param name="child">생성된 자식의 ChildType 값이 복사될 변수입니다.</param>
/// <returns>주어진 위치에 자식 사운드를 등록하는 데 실패한 경우와 그 원인을 나타내는 AudioError입니다.</returns>
public AudioError RegisterChildAt3DPos(string name, Vector3 position, out ChildType child);
/// <summary>
/// 주어진 GameObject에 새로운 자식 사운드를 등록하여 나중에 해당 ChildType 값으로 참조할 수 있게 합니다.
/// </summary>
/// <param name="name">등록된 사운드의 이름입니다.</param>
/// <param name="attachGameObject">자식 사운드를 부착할 GameObject입니다.</param>
/// <param name="child">생성된 자식의 ChildType 값이 복사될 변수입니다.</param>
/// <returns>주어진 GameObject에 자식 사운드를 등록하는 데 실패한 경우와 그 원인을 나타내는 AudioError입니다.</returns>
public AudioError RegisterChildAttachedToGo(string name, GameObject attachGameObject, out ChildType child);
/// <summary>
/// 이전에 등록된 자식 사운드의 기본 AudioSource 컴포넌트를 등록 해제하고 삭제합니다.
/// </summary>
/// <param name="name">등록된 사운드의 이름입니다.</param>
/// <param name="child">등록 해제할 자식의 ChildType입니다.</param>
/// <returns>자식 사운드 등록 해제 및 삭제 실패 여부와 그 원인을 나타내는 AudioError입니다.</returns>
public AudioError DeregisterChild(string name, ChildType child);
/// <summary>
/// 주어진 지연 시간 후에 주어진 ChildType으로 사운드를 재생합니다.
/// </summary>
/// <param name="name">등록된 사운드의 이름입니다.</param>
/// <param name="delay">사운드를 재생하기 전 지연 시간(초)입니다.</param>
/// <param name="child">메서드를 호출할 자식 객체입니다.</param>
/// <returns>지정된 지연 후에 사운드를 재생하는 데 실패한 경우와 그 원인을 나타내는 AudioError입니다.</returns>
public AudioError PlayDelayed(string name, float delay, ChildType child = Constants.DEFAULT_CHILD_TYPE);
/// <summary>
/// 주어진 ChildType으로 사운드를 한 번 재생합니다.
/// 이 메서드를 사용하면 동일한 사운드의 여러 인스턴스를 동시에 실행할 수 있습니다.
/// </summary>
/// <param name="name">등록된 사운드의 이름입니다.</param>
/// <param name="child">메서드를 호출할 자식 객체입니다.</param>
/// <returns>한 번 사운드를 재생하는 데 실패한 경우와 그 원인을 나타내는 AudioError입니다.</returns>
public AudioError PlayOneShot(string name, ChildType child = Constants.DEFAULT_CHILD_TYPE);
/// <summary>
/// 주어진 사운드와 ChildType의 피치를 주어진 최소값과 최대값 사이의 임의의 값으로 설정합니다.
/// </summary>
/// <param name="name">등록된 사운드의 이름입니다.</param>
/// <param name="minPitch">사운드가 가질 수 있는 최소 피치 값입니다.</param>
/// <param name="maxPitch">사운드가 가질 수 있는 최대 피치 값입니다.</param>
/// <param name="child">메서드를 호출할 자식 객체입니다.</param>
/// <returns>피치 변경 실패 여부와 그 원인을 나타내는 AudioError입니다.</returns>
public AudioError ChangePitch(string name, float minPitch, float maxPitch, ChildType child = Constants.DEFAULT_CHILD_TYPE);
/// <summary>
/// 주어진 사운드와 ChildType의 기본 AudioClip의 길이를 가져옵니다.
/// </summary>
/// <param name="name">등록된 사운드의 이름입니다.</param>
/// <param name="length">클립 길이(초)가 복사될 변수입니다. 실패 시 <see cref="float.NaN"/>이 저장됩니다.</param>
/// <param name="child">메서드를 호출할 자식 객체입니다.</param>
/// <returns>클립 길이를 가져오는 데 실패한 경우와 그 원인을 나타내는 AudioError입니다.</returns>
public AudioError GetClipLength(string name, out double length, ChildType child = Constants.DEFAULT_CHILD_TYPE);
/// <summary>
/// 미래의 정확한 주어진 시간에 주어진 ChildType으로 사운드를 재생합니다.
/// 백그라운드에서 오디오 시스템의 DSP 시간을 사용하므로 PlayDelayed, Time.time 및 WaitForSeconds보다 훨씬 더 정확합니다.
/// </summary>
/// <param name="name">등록된 사운드의 이름입니다.</param>
/// <param name="time">사운드를 재생할 미래 시간(초)입니다.</param>
/// <param name="child">메서드를 호출할 자식 객체입니다.</param>
/// <returns>정확한 시간에 사운드를 재생하는 데 실패한 경우와 그 원인을 나타내는 AudioError입니다.</returns>
public AudioError PlayScheduled(string name, double time, ChildType child = Constants.DEFAULT_CHILD_TYPE);
/// <summary>
/// 주어진 ChildType으로 사운드를 중지합니다.
/// </summary>
/// <param name="name">등록된 사운드의 이름입니다.</param>
/// <param name="child">메서드를 호출할 자식 객체입니다.</param>
/// <returns>사운드 중지 실패 여부와 그 원인을 나타내는 AudioError입니다.</returns>
public AudioError Stop(string name, ChildType child = Constants.DEFAULT_CHILD_TYPE);
/// <summary>
/// 주어진 ChildType으로 사운드를 음소거하거나 음소거를 해제합니다.
/// </summary>
/// <param name="name">등록된 사운드의 이름입니다.</param>
/// <param name="child">메서드를 호출할 자식 객체입니다.</param>
/// <returns>사운드 음소거 또는 음소거 해제 실패 여부와 그 원인을 나타내는 AudioError입니다.</returns>
public AudioError ToggleMute(string name, ChildType child = Constants.DEFAULT_CHILD_TYPE);
/// <summary>
/// 주어진 ChildType으로 사운드를 일시 중지하거나 재개합니다.
/// </summary>
/// <param name="name">등록된 사운드의 이름입니다.</param>
/// <param name="child">메서드를 호출할 자식 객체입니다.</param>
/// <returns>사운드 일시 중지 또는 재개 실패 여부와 그 원인을 나타내는 AudioError입니다.</returns>
public AudioError TogglePause(string name, ChildType child = Constants.DEFAULT_CHILD_TYPE);
/// <summary>
/// 주어진 SourceChangedCallback을 구독하여 구독된 사운드의 기본 AudioSourceWrapper가 변경되었을 때 호출되도록 합니다.
/// </summary>
/// <param name="name">등록된 사운드의 이름입니다.</param>
/// <param name="callback">사운드가 변경되었을 때 호출될 콜백입니다.</param>
/// <returns>콜백 구독 실패 여부와 그 원인을 나타내는 AudioError입니다.</returns>
public AudioError SubscribeSourceChanged(string name, SourceChangedCallback callback);
/// <summary>
/// 이전에 SubscribeSourceChanged를 통해 구독한 SourceChangedCallback의 구독을 해제하여
/// 주어진 기본 AudioSourceWrapper가 있는 사운드가 변경되었을 때 더 이상 호출되지 않도록 합니다.
/// </summary>
/// <param name="name">등록된 사운드의 이름입니다.</param>
/// <param name="callback">더 이상 호출되지 않을 콜백입니다.</param>
/// <returns>콜백 구독 해제 실패 여부와 그 원인을 나타내는 AudioError입니다.</returns>
public AudioError UnsubscribeSourceChanged(string name, SourceChangedCallback callback);
/// <summary>
/// 주어진 사운드의 재생 시간이 해당 진행률 지점에 도달하거나 초과했을 때 호출되는
/// ProgressCoroutineCallback을 구독합니다.
/// 콜백의 반환 값에 따라 동일한 진행률에 대해 다시 구독될지 결정됩니다.
/// </summary>
/// <param name="name">등록된 사운드의 이름입니다.</param>
/// <param name="progress">콜백을 호출할 사운드 재생 진행률(0에서 1 사이)입니다.</param>
/// <param name="callback">사운드가 해당 진행률에 도달했을 때 호출될 콜백입니다.</param>
/// <returns>콜백 구독 실패 여부와 그 원인을 나타내는 AudioError입니다.</returns>
public AudioError SubscribeProgressCoroutine(string name, float progress, ProgressCoroutineCallback callback);
/// <summary>
/// 이전에 SubscribeProgressCoroutine을 통해 구독한 ProgressCoroutineCallback의 구독을 해제하여
/// 주어진 진행률에 도달했을 때 더 이상 호출되지 않도록 합니다.
/// </summary>
/// <param name="name">등록된 사운드의 이름입니다.</param>
/// <param name="progress">콜백 호출을 원하지 않는 진행률(0에서 1 사이)입니다.</param>
/// <returns>콜백 구독 해제 실패 여부와 그 원인을 나타내는 AudioError입니다.</returns>
public AudioError UnsubscribeProgressCoroutine(string name, float progress);
/// <summary>
/// 주어진 ChildType에 대해 사운드의 현재 진행률(완료 비율 0에서 1)을 반환합니다.
/// </summary>
/// <param name="name">등록된 사운드의 이름입니다.</param>
/// <param name="progress">진행률이 복사될 변수입니다. 실패 시 <see cref="float.NaN"/>이 저장됩니다.</param>
/// <param name="child">메서드를 호출할 자식 객체입니다.</param>
/// <returns>진행률을 가져오는 데 실패한 경우와 그 원인을 나타내는 AudioError입니다.</returns>
public AudioError GetProgress(string name, out float progress, ChildType child = Constants.DEFAULT_CHILD_TYPE);
/// <summary>
/// 주어진 사운드에서 해당하는 AudioSourceWrapper를 가져옵니다.
/// </summary>
/// <param name="name">등록된 사운드의 이름입니다.</param>
/// <param name="source">AudioSourceWrapper가 복사될 변수입니다.</param>
/// <returns>AudioSourceWrapper 가져오기 실패 여부와 그 원인을 나타내는 AudioError입니다.</returns>
public AudioError TryGetSource(string name, out AudioSourceWrapper source);
/// <summary>
/// 주어진 ChildType을 가진 사운드의 피치를 주어진 시간(duration) 동안 endValue로 변경합니다.
/// </summary>
/// <param name="name">등록된 사운드의 이름입니다.</param>
/// <param name="endValue">도달하려는 최종 피치 값입니다.</param>
/// <param name="duration">최종 값에 도달하는 데 필요한 총 시간입니다.</param>
/// <param name="child">메서드를 호출할 자식 객체입니다.</param>
/// <returns>피치 변경 실패 여부와 그 원인을 나타내는 AudioError입니다.</returns>
public AudioError LerpPitch(string name, float endValue, float duration = Constants.DEFAULT_DURATION, ChildType child = Constants.DEFAULT_CHILD_TYPE);
/// <summary>
/// 주어진 ChildType을 가진 사운드의 볼륨을 주어진 시간(duration) 동안 endValue로 변경합니다.
/// </summary>
/// <param name="name">등록된 사운드의 이름입니다.</param>
/// <param name="endValue">도달하려는 최종 볼륨 값입니다.</param>
/// <param name="duration">최종 값에 도달하는 데 필요한 총 시간입니다.</param>
/// <param name="child">메서드를 호출할 자식 객체입니다.</param>
/// <returns>볼륨 변경 실패 여부와 그 원인을 나타내는 AudioError입니다.</returns>
public AudioError LerpVolume(string name, float endValue, float duration = Constants.DEFAULT_DURATION, ChildType child = Constants.DEFAULT_CHILD_TYPE);
/// <summary>
/// 주어진 사운드의 전체 AudioMixerGroup에 대해 지정된 노출 매개변수의 값을 주어진 newValue로 변경합니다.
/// <see cref="AudioMixerGroup"/>의 볼륨과 같은 일부 값은 로그 스케일로 작동하므로,
/// 예상대로 값을 정확히 변경하려면 전달하는 값에 <see cref="Mathf.Log10()"/>을 적용하십시오.
/// </summary>
/// <param name="name">등록된 사운드의 이름입니다.</param>
/// <param name="exposedParameterName">변경하려는 노출된 매개변수의 이름입니다.</param>
/// <param name="newValue">새로 설정할 노출된 매개변수 값입니다.</param>
/// <returns>노출된 매개변수 변경 실패 여부와 그 원인을 나타내는 AudioError입니다.</returns>
public AudioError ChangeGroupValue(string name, string exposedParameterName, float newValue);
/// <summary>
/// 주어진 사운드의 전체 AudioMixerGroup에 대해 지정된 노출 매개변수의 현재 값을 가져옵니다.
/// </summary>
/// <param name="name">등록된 사운드의 이름입니다.</param>
/// <param name="exposedParameterName">가져올 노출된 매개변수의 이름입니다.</param>
/// <param name="currentValue">현재 노출된 매개변수 값이 복사될 변수입니다. 실패 시 <see cref="float.NaN"/>이 저장됩니다.</param>
/// <returns>노출된 매개변수 값을 가져오는 데 실패한 경우와 그 원인을 나타내는 AudioError입니다.</returns>
public AudioError GetGroupValue(string name, string exposedParameterName, out float currentValue);
/// <summary>
/// 주어진 사운드의 전체 AudioMixerGroup에 대해 지정된 노출 매개변수 값을 기본값으로 재설정합니다.
/// </summary>
/// <param name="name">등록된 사운드의 이름입니다.</param>
/// <param name="exposedParameterName">재설정할 노출된 매개변수의 이름입니다.</param>
/// <returns>노출된 매개변수 재설정 실패 여부와 그 원인을 나타내는 AudioError입니다.</returns>
public AudioError ResetGroupValue(string name, string exposedParameterName);
/// <summary>
/// 주어진 사운드의 전체 AudioMixerGroup에 대해 지정된 노출 매개변수 값을 주어진 시간(duration) 동안 최종값(endValue)으로 변경합니다.
/// AudioMixer에 의해 프레임 간 보간이 추가로 적용되므로 LerpVolume이나 LerpPitch보다 더 부드러운 결과를 생성합니다.
/// </summary>
/// <param name="name">등록된 사운드의 이름입니다.</param>
/// <param name="exposedParameterName">변경하려는 노출된 매개변수의 이름입니다.</param>
/// <param name="endValue">도달하려는 최종 값입니다.</param>
/// <param name="duration">최종 값에 도달하는 데 필요한 총 시간입니다.</param>
/// <returns>노출 매개변수 변경 실패 여부와 그 원인을 나타내는 AudioError입니다.</returns>
public AudioError LerpGroupValue(string name, string exposedParameterName, float endValue, float duration = Constants.DEFAULT_DURATION);
/// <summary>
/// 주어진 ChildType을 가진 사운드에서 AudioMixerGroup을 제거하여 더 이상 해당 설정의 영향을 받지 않도록 합니다.
/// </summary>
/// <param name="name">등록된 사운드의 이름입니다.</param>
/// <param name="child">메서드를 호출할 자식 객체입니다.</param>
/// <returns>AudioMixerGroup 제거 실패 여부와 그 원인을 나타내는 AudioError입니다.</returns>
public AudioError RemoveGroup(string name, ChildType child = Constants.DEFAULT_CHILD_TYPE);
/// <summary>
/// 주어진 ChildType을 가진 사운드에 AudioMixerGroup을 추가하여 해당 설정의 영향을 받도록 합니다.
/// </summary>
/// <param name="name">등록된 사운드의 이름입니다.</param>
/// <param name="mixerGroup">사운드가 영향을 받을 AudioMixerGroup입니다.</param>
/// <param name="child">메서드를 호출할 자식 객체입니다.</param>
/// <returns>AudioMixerGroup 추가 실패 여부와 그 원인을 나타내는 AudioError입니다.</returns>
public AudioError AddGroup(string name, AudioMixerGroup mixerGroup, ChildType child = Constants.DEFAULT_CHILD_TYPE);
/// <summary>
/// AudioManager에서 사운드의 기본 AudioSource 컴포넌트를 등록 해제하고 삭제합니다.
/// </summary>
/// <param name="name">제거할 등록된 사운드의 이름입니다.</param>
/// <returns>사운드 제거 실패 여부와 그 원인을 나타내는 AudioError입니다.</returns>
public AudioError RemoveSound(string name);
2. AudioSourceWrapper 클래스
AudioSourceWrapper는 AudioSource컴포넌트를 감싸는 클래스입니다. 이 클래스는 AudioSource의 다양한 속성을 관리하고, 변경 시 콜백을 호출할 수 있는 기능을 제공합니다. 이를 통해 오디오 소스의 상태를 쉽게 추적하고 관리할 수 있습니다.
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Audio;
namespace AudioManager.Core
{
/// <summary>
/// 기본 <see cref="AudioSource"/>의 값이 변경될 때마다 호출되는 구독 가능한 콜백입니다.
/// </summary>
/// <param name="changedSource">접근되어 일부 값이 변경된 소스입니다.</param>
public delegate void SourceChangedCallback(AudioSourceWrapper changedSource);
/// <summary>
/// 지정된 <see cref="ChildType"/>에 맞는 모든 자식에 대해
/// <see cref="AudioSourceWrapper.InvokeChild"/>가 호출될 때마다 호출되는 구독 가능한 콜백입니다.
/// </summary>
/// <param name="childSource">메서드를 호출하려는 소스입니다.</param>
public delegate void InvokeCallback(AudioSource childSource);
/// <summary>
/// 지정된 <see cref="ChildType"/>에 맞는 모든 자식에 대해
/// <see cref="AudioSourceWrapper.InvokeChild"/>가 호출될 때마다 반환 값이 필요한 구독 가능한 콜백입니다.
/// </summary>
/// <param name="childSource">메서드를 호출하고 주어진 타입의 값을 반환하려는 소스입니다.</param>
/// <returns>지정된 타입 <see cref="T"/>의 값입니다.</returns>
public delegate T InvokeCallback<T>(AudioSource childSource);
/// <summary>
/// 주어진 <see cref="AudioSourceWrapper"/>의 값을 변경하고자 할 때 호출되는 구독 가능한 콜백입니다.
/// </summary>
/// <param name="value">주어진 소스에 설정하고자 하는 값입니다.</param>
/// <param name="source">주어진 값으로 변경하고자 하는 소스입니다.</param>
public delegate void SetCallback<T>(T value, AudioSourceWrapper source);
public class AudioSourceWrapper
{
// 비공개 읽기 전용 멤버 변수들.
private readonly AudioSource m_wrappedSource;
private readonly IDictionary<ChildType, AudioSource> m_childrenDictionary;
// 비공개 멤버 변수들.
private SourceChangedCallback m_cb;
// 비공개 delegate 헬퍼.
private delegate void SetValueCallback<T>(T value, AudioSource source);
private delegate T GetValueCallback<T>(AudioSource source);
public AudioSourceWrapper(AudioSource source)
{
m_cb = null;
m_wrappedSource = source;
m_childrenDictionary = new Dictionary<ChildType, AudioSource>();
}
public ICollection<AudioSource> GetChildren()
{
return m_childrenDictionary.Values;
}
public IEnumerator<KeyValuePair<ChildType, AudioSource>> GetEnumerator()
{
return m_childrenDictionary.GetEnumerator();
...
set { Set(value, Loop, (x, s) => s.loop = x); }
}
public bool Spatialize
{
get { return GetS((s) => s.spatialize); }
set { Set(value, Spatialize, (x, s) => s.spatialize = x); }
}
public bool Mute
{
get { return GetS((s) => s.mute); }
set { Set(value, Mute, (x, s) => s.mute = x); }
}
//************************************************************************************************************************
// 비공개 섹션
//************************************************************************************************************************
private void Set<T>(T newValue, T currValue, SetValueCallback<T> set)
{
3. AudioError 열거형
AudioError는 오디오 작업 중 발생할 수 있는 다양한 오류를 정의하는 열거형입니다. 이 열거형은 오류의 종류를 명확히 구분하여, 오류 처리 및 디버깅을 용이하게 합니다.
namespace AudioManager.Core {
public enum AudioError {
OK,
DOES_NOT_EXIST,
ALREADY_EXISTS,
INVALID_PATH,
INVALID_END_VALUE,
INVALID_TIME,
INVALID_PROGRESS,
MIXER_NOT_EXPOSED,
MISSING_SOURCE,
MISSING_MIXER_GROUP,
CAN_NOT_BE_3D,
NOT_INITIALIZED,
MISSING_CLIP,
MISSING_PARENT,
INVALID_PARENT,
ALREADY_SUBSCRIBED,
NOT_SUBSCRIBED,
MISSING_WRAPPER,
5. Constants 구조체
Contants 구조체는 오디오 관리에 사용되는 다양한 상수를 정의합니다. 이 구조체는 기본 볼륨, 피치, 거리 등과 같은 오디오 설정의 기본값으 제공합니다.
using UnityEngine;
using UnityEngine.Audio;
namespace AudioManager.Core
{
public struct Constants
{
// 양의 피치로 사운드를 재생할 때 IEnumerator에서 감지할 수 있는 최대 진행률입니다.
public const float MAX_PROGRESS = 0.99f;
// 음의 피치로 사운드를 재생할 때 IEnumerator에서 감지할 수 있는 최소 진행률입니다.
public const float MIN_PROGRESS = 1f - MAX_PROGRESS;
// 2D로 간주되는 최대 공간 혼합(spatial blend) 값입니다.
public const float SPATIAL_BLEND_2D = 0f;
// 주어진 IAudioManager가 아직 초기화되지 않았을 때 반환되는 AudioError입니다.
public const AudioError NULL_AUDIO_ERROR = AudioError.NOT_INITIALIZED;
// 메서드 매개변수의 기본값들입니다.
public const float F_NULL_VALUE = float.NaN;
public const double D_NULL_VALUE = double.NaN;
public const float DEFAULT_VOLUME = 1f;
public const float DEFAULT_PITCH = 1f;
public const float DEFAULT_REVERSE_PITCH = -1f;
public const bool DEFAULT_LOOP = false;
public const float DEFAULT_DURATION = 1f;
public const AudioSource DEFAULT_SOURCE = null;
public const AudioMixerGroup DEFAULT_GROUP = null;
public const float DEFAULT_MIN_DISTANCE = 1f;
public const float DEFAULT_MAX_DISTANCE = 500f;
public const float DEFAULT_BLEND = 1f;
public const float DEFAULT_ANGLE = 0f;
public const float DEFAULT_DOPPLER = 1f;
public const ChildType DEFAULT_CHILD_TYPE = ChildType.PARENT;
public const AudioRolloffMode DEFAULT_MODE = AudioRolloffMode.Logarithmic;
}
}
학습한 점
- 모듈화된 설계: 이 프레임워크는 인터페이스와 클래스를 통해 기능을 모듈화하여, 유지보수성과 확장성을 높였습니다.
- 콜백 시스템: 오디오 소스의 상태 변경 시 콜백을 활용하여, 실시간으로 상태를 추적하고 반응할 수 있는 구조를 배웠습니다.
- 오류 처리: 열거형을 통해 명확한 오류 처리를 구현하여, 디버깅과 유지보수를 용이하게 했습니다.
- 3D 오디오 관리: 3D 공간에서의 오디오 재생 및 관리 방법을 학습했습니다.
+ 다양한 사용 방법 정리
1. 3D 위치에서 사운드 재생
3D공간에서 특정 위치에 사운드를 재생하려면 RegisterChildAt3DPos 메서드를 사용하여 사운드를 등록하고, Play 메서드를 호출합니다.
private void InitLerpIn3DSoundAtPosExample() {
am.SubscribeProgressCoroutine(sound3D.soundName, 0f, SongProgressCallback);
am.RegisterChildAt3DPos(sound3D.soundName, position3D, out ChildType child);
am.Play(sound3D.soundName, child);
}
2. 특정 구간 반복 재생
사운드의 특정 구간을 반복 재생하려면 SubscribeProgressCoroutine을 사용하여 구간의 끝에 도달했을 때 콜백을 호출하도록 설정합니다.
private void InitLoopSubSectionExample() {
am.TryGetSource(loopSound.soundName, out var source);
source.Time = loopStart;
float progress = (loopEnd / source.Source.clip.length);
am.SubscribeProgressCoroutine(loopSound.soundName, progress, SongProgressCallback);
am.Play(loopSound.soundName);
}
3. 두 곡을 순차적으로 재생
첫번째 곡이 끝난 후 두 번째 곡을 재생하려면 PlayScheduled 메서드를 사용하여 두 번째 곡의 재생 시간을 예약합니다.
private void InitPlaySongAfterAnotherExample() {
am.PlayScheduled(firstSound.soundName, 0d);
am.GetClipLength(firstSound.soundName, out double time);
am.PlayScheduled(secondSound.soundName, time);
}
4. 사운드 페이드 인
사운드를 서서히 페이드 인 하려면 LerpVolume 메서드를 사용하여 볼륨을 점진적으로 증가시킵니다.
private void InitFadeInSongExample() {
am.SubscribeProgressCoroutine(fadeInSong.soundName, 0f, SongProgressCallback);
am.Play(fadeInSong.soundName);
}
private ProgressResponse HandleFadeInSongExample(string name) {
am.TryGetSource(name, out var source);
source.Volume = 0f;
am.LerpVolume(name, fadeInEndVolume, clipFadeInTime);
return ProgressResponse.RESUB_IN_LOOP;
}
5. UI를 통한 볼륨 조절
UI 슬라이더를 사용하여 오디오 믹서 그룹의 볼륨을 조절하려면 ChangeGroupValue 메서드를 사용합니다.
public void HandleChangeVolumeViaUIExample(float sliderValue) {
float newVolume = Mathf.Log10(sliderValue) * 20;
am.ChangeGroupValue(groupSong.soundName, EXPOSED_VOLUME_NAME, newVolume);
}
6. 사운드 역재생
사운드를 역재생하려면 SetPlaybackDirection 메서드를 사용하여 피치를 음수로 설정합니다.
private void InitPlaySongInReverseExample() {
am.SetPlaybackDirection(reverseSound.soundName, directionPitch);
am.Play(reverseSound.soundName);
}