이전에 업데이트 내 인풋함수로 키보드 클릭 이벤트를 통해 확인하다가 불편하고, 게임의 플레이 흐름에 영향을 미칠까봐 에디터 프로그래밍으로 변경했다.
1. 이전
2. 에디터 프로그래밍으로 전환한 이유
3. 코드
4. 후기
1. 이전
이전 코드는 다음과 같다.
이 때도 cursor을 이용해, 다음과 같이 프롬프트를 작성하고 테스트 코드를 받았다.
@Assets/Scripts/AudioManager.cs 를 구현했는데 Resources/Sounds에 있는 파일들을
잘 재생하는지 테스트하고 싶어. 테스트 코드랑 방법 줘
using UnityEngine;
// AudioManager 기능 테스트
public class AudioManagerTest : MonoBehaviour
{
[Header("테스트 설정")]
[SerializeField] private bool autoTestOnStart = true;
[SerializeField] private bool enableManualTest = true;
private void Start()
{
if (autoTestOnStart)
{
Debug.Log("=== AudioManager 테스트 시작 ===");
TestAudioManagerInstance();
TestBGMPlay();
TestSFXPlay();
TestMute();
TestStopBGM();
TestInvalidAudioClip();
TestClearCache();
Debug.Log("=== AudioManager 테스트 완료 ===");
}
}
private void Update()
{
if (!enableManualTest) return;
// 수동 테스트: 키보드 입력으로 실제 소리 재생 확인
// BGM 테스트
if (Input.GetKeyDown(KeyCode.B))
{
AudioManager.Instance?.PlayBGM("lobby");
Debug.Log("[Manual Test] BGM 재생: lobby (B 키)");
}
// SFX 테스트
if (Input.GetKeyDown(KeyCode.Alpha1))
{
AudioManager.Instance?.PlaySFX("ui_button_click");
Debug.Log("[Manual Test] SFX 재생: ui_button_click (1 키)");
}
if (Input.GetKeyDown(KeyCode.Alpha2))
{
AudioManager.Instance?.PlaySFX("stage_clear");
Debug.Log("[Manual Test] SFX 재생: stage_clear (2 키)");
}
if (Input.GetKeyDown(KeyCode.Alpha3))
{
AudioManager.Instance?.PlaySFX("chapter_clear");
Debug.Log("[Manual Test] SFX 재생: chapter_clear (3 키)");
}
// BGM 정지
if (Input.GetKeyDown(KeyCode.S))
{
AudioManager.Instance?.StopBGM();
Debug.Log("[Manual Test] BGM 정지 (S 키)");
}
// 음소거 토글
if (Input.GetKeyDown(KeyCode.M))
{
bool isMuted = AudioManager.Instance != null &&
(AudioManager.Instance.GetComponentInChildren<AudioSource>()?.mute ?? false);
AudioManager.Instance?.Mute(!isMuted);
Debug.Log($"[Manual Test] 음소거: {!isMuted} (M 키)");
}
// 캐시 클리어
if (Input.GetKeyDown(KeyCode.C))
{
AudioManager.Instance?.ClearCache();
Debug.Log("[Manual Test] 캐시 클리어 (C 키)");
}
// 도움말 표시
if (Input.GetKeyDown(KeyCode.H))
{
ShowManualTestHelp();
}
}
// AudioManager 인스턴스 확인
private void TestAudioManagerInstance()
{
Debug.Log("\n--- AudioManager 인스턴스 테스트 ---");
AudioManager manager = AudioManager.Instance;
bool testSuccess = manager != null;
Debug.Log($"[Test 1] AudioManager 인스턴스 확인");
Debug.Log($" 인스턴스 존재: {manager != null}");
Debug.Log($" 성공: {testSuccess}");
if (!testSuccess)
{
Debug.LogError(" AudioManager 인스턴스를 가져올 수 없습니다. 테스트를 중단합니다.");
}
}
// BGM 재생 테스트
private void TestBGMPlay()
{
Debug.Log("\n--- BGM 재생 테스트 ---");
AudioManager manager = AudioManager.Instance;
if (manager == null)
{
Debug.LogError("[Test] AudioManager 인스턴스를 가져올 수 없습니다.");
return;
}
// 테스트 1: 정상적인 BGM 재생
Debug.Log("[Test 1] BGM 재생 - lobby");
manager.PlayBGM("lobby", 0.5f);
bool test1Success = true; // 실제 재생 여부는 수동으로 확인 필요
Debug.Log($" BGM 재생 요청 완료 (실제 재생 여부는 수동으로 확인하세요)");
Debug.Log($" 성공: {test1Success}");
// 테스트 2: 빈 문자열 처리
Debug.Log("[Test 2] BGM 재생 - 빈 문자열");
manager.PlayBGM("");
bool test2Success = true; // 에러 없이 처리되면 성공
Debug.Log($" 빈 문자열 처리 완료 (에러 없음)");
Debug.Log($" 성공: {test2Success}");
// 테스트 3: null 처리
Debug.Log("[Test 3] BGM 재생 - null");
manager.PlayBGM(null);
bool test3Success = true; // 에러 없이 처리되면 성공
Debug.Log($" null 처리 완료 (에러 없음)");
Debug.Log($" 성공: {test3Success}");
// 테스트 4: 같은 BGM 중복 재생 방지
Debug.Log("[Test 4] BGM 재생 - 중복 재생 방지");
manager.PlayBGM("lobby");
manager.PlayBGM("lobby"); // 같은 BGM 다시 재생 시도
bool test4Success = true; // 중복 재생 방지 로직 확인
Debug.Log($" 중복 재생 방지 확인 완료");
Debug.Log($" 성공: {test4Success}");
}
// SFX 재생 테스트
private void TestSFXPlay()
{
Debug.Log("\n--- SFX 재생 테스트 ---");
AudioManager manager = AudioManager.Instance;
if (manager == null)
{
Debug.LogError("[Test] AudioManager 인스턴스를 가져올 수 없습니다.");
return;
}
// 테스트 1: 정상적인 SFX 재생
Debug.Log("[Test 1] SFX 재생 - ui_button_click");
manager.PlaySFX("ui_button_click", 0.7f);
bool test1Success = true;
Debug.Log($" SFX 재생 요청 완료 (실제 재생 여부는 수동으로 확인하세요)");
Debug.Log($" 성공: {test1Success}");
Debug.Log("[Test 2] SFX 재생 - stage_clear");
manager.PlaySFX("stage_clear");
bool test2Success = true;
Debug.Log($" SFX 재생 요청 완료");
Debug.Log($" 성공: {test2Success}");
Debug.Log("[Test 3] SFX 재생 - chapter_clear");
manager.PlaySFX("chapter_clear");
bool test3Success = true;
Debug.Log($" SFX 재생 요청 완료");
Debug.Log($" 성공: {test3Success}");
// 테스트 4: 빈 문자열 처리
Debug.Log("[Test 4] SFX 재생 - 빈 문자열");
manager.PlaySFX("");
bool test4Success = true;
Debug.Log($" 빈 문자열 처리 완료 (에러 없음)");
Debug.Log($" 성공: {test4Success}");
// 테스트 5: null 처리
Debug.Log("[Test 5] SFX 재생 - null");
manager.PlaySFX(null);
bool test5Success = true;
Debug.Log($" null 처리 완료 (에러 없음)");
Debug.Log($" 성공: {test5Success}");
}
// 음소거 기능 테스트
private void TestMute()
{
Debug.Log("\n--- 음소거 기능 테스트 ---");
AudioManager manager = AudioManager.Instance;
if (manager == null)
{
Debug.LogError("[Test] AudioManager 인스턴스를 가져올 수 없습니다.");
return;
}
// 테스트 1: 음소거 활성화
Debug.Log("[Test 1] 음소거 활성화");
manager.Mute(true);
bool test1Success = true;
Debug.Log($" 음소거 활성화 완료");
Debug.Log($" 성공: {test1Success}");
// 테스트 2: 음소거 해제
Debug.Log("[Test 2] 음소거 해제");
manager.Mute(false);
bool test2Success = true;
Debug.Log($" 음소거 해제 완료");
Debug.Log($" 성공: {test2Success}");
}
// BGM 정지 테스트
private void TestStopBGM()
{
Debug.Log("\n--- BGM 정지 테스트 ---");
AudioManager manager = AudioManager.Instance;
if (manager == null)
{
Debug.LogError("[Test] AudioManager 인스턴스를 가져올 수 없습니다.");
return;
}
// 먼저 BGM 재생
manager.PlayBGM("lobby");
// 테스트: BGM 정지
Debug.Log("[Test] BGM 정지");
manager.StopBGM();
bool testSuccess = true;
Debug.Log($" BGM 정지 요청 완료");
Debug.Log($" 성공: {testSuccess}");
}
// 존재하지 않는 오디오 클립 테스트
private void TestInvalidAudioClip()
{
Debug.Log("\n--- 존재하지 않는 오디오 클립 테스트 ---");
AudioManager manager = AudioManager.Instance;
if (manager == null)
{
Debug.LogError("[Test] AudioManager 인스턴스를 가져올 수 없습니다.");
return;
}
// 테스트 1: 존재하지 않는 BGM
Debug.Log("[Test 1] 존재하지 않는 BGM 재생");
manager.PlayBGM("nonexistent_bgm");
bool test1Success = true; // 에러 없이 처리되면 성공
Debug.Log($" 존재하지 않는 BGM 처리 완료 (에러 없음, 로그 확인 필요)");
Debug.Log($" 성공: {test1Success}");
// 테스트 2: 존재하지 않는 SFX
Debug.Log("[Test 2] 존재하지 않는 SFX 재생");
manager.PlaySFX("nonexistent_sfx");
bool test2Success = true; // 에러 없이 처리되면 성공
Debug.Log($" 존재하지 않는 SFX 처리 완료 (에러 없음, 로그 확인 필요)");
Debug.Log($" 성공: {test2Success}");
}
// 캐시 클리어 테스트
private void TestClearCache()
{
Debug.Log("\n--- 캐시 클리어 테스트 ---");
AudioManager manager = AudioManager.Instance;
if (manager == null)
{
Debug.LogError("[Test] AudioManager 인스턴스를 가져올 수 없습니다.");
return;
}
// 먼저 오디오 클립 로드
manager.PlayBGM("lobby");
manager.PlaySFX("ui_button_click");
// 테스트: 캐시 클리어
Debug.Log("[Test] 캐시 클리어");
manager.ClearCache();
bool testSuccess = true;
Debug.Log($" 캐시 클리어 요청 완료");
Debug.Log($" 성공: {testSuccess}");
}
// 수동 테스트 도움말 표시
private void ShowManualTestHelp()
{
Debug.Log("\n=== 수동 테스트 도움말 ===");
Debug.Log("B 키: BGM 재생 (lobby)");
Debug.Log("1 키: SFX 재생 (ui_button_click)");
Debug.Log("2 키: SFX 재생 (stage_clear)");
Debug.Log("3 키: SFX 재생 (chapter_clear)");
Debug.Log("S 키: BGM 정지");
Debug.Log("M 키: 음소거 토글");
Debug.Log("C 키: 캐시 클리어");
Debug.Log("H 키: 이 도움말 표시");
Debug.Log("=======================\n");
}
}
위 경우에는 키보드 입력으로 실제 소리를 확인해야 했다.
그리고 이 때 b키를 눌렀을 때 소리가 나지 않았는데, 다른 음악을 넣으니 해결되어 음원 문제라는 사실을 알았다...
2. 에디터 프로그래밍으로 전환한 이유
에디터 프로그래밍으로 해당 테스트 코드를 남긴 이유는 사운드 파일을 테스트할 때도 해당 코드를 재사용할 수 있고, 유니티 버전을 올리거나 오디오매니저를 테스트할 때에 사용해야겠다는 생각이 들었기 때문이다. 하지만 위와 같은 방식의 키보드 이벤트로 남겨둘 경우, 게임 흐름에 직접적으로 영향을 주고, Update문에서 지속적으로 불러온다. 그리고 코드를 수정할 필요 없이 원하는 음원이 있으면 해당 음원명으로 변경하고 테스트하면 때문에 변경하기로 결정했다. 버튼UI를 추가하기에는 비효율적이고 이후 릴리즈때는 영향을 주고 싶지 않아 에디터 프로그래밍으로 선택했다.
3. 코드
코드는 다음과 같다.
using UnityEngine;
namespace BalancingLibra.Tests
{
public class AudioManagerTest : MonoBehaviour
{
[Header("Test Settings")]
[Tooltip("테스트할 BGM 파일명 (확장자 제외)")]
public string bgmName = "lobby";
[Tooltip("테스트할 SFX 파일명 (확장자 제외)")]
public string sfxName = "ui_button_click";
[Range(0f, 1f)]
public float testVolume = 1.0f;
[ContextMenu("1. Play BGM")]
private void TestPlayBGM()
{
if (!IsPlaying()) return;
Debug.Log($"[AudioTester] BGM 재생 요청: {bgmName}");
AudioManager.Instance.PlayBGM(bgmName, testVolume);
}
[ContextMenu("2. Stop BGM")]
private void TestStopBGM()
{
if (!IsPlaying()) return;
Debug.Log("[AudioTester] BGM 정지 요청");
AudioManager.Instance.StopBGM();
}
[ContextMenu("3. Play SFX")]
private void TestPlaySFX()
{
if (!IsPlaying()) return;
Debug.Log($"[AudioTester] SFX 재생 요청: {sfxName}");
AudioManager.Instance.PlaySFX(sfxName, testVolume);
}
[ContextMenu("4. Mute ON")]
private void TestMuteOn()
{
if (!IsPlaying()) return;
Debug.Log("[AudioTester] 전체 음소거");
AudioManager.Instance.Mute(true);
}
[ContextMenu("5. Mute OFF")]
private void TestMuteOff()
{
if (!IsPlaying()) return;
Debug.Log("[AudioTester] 음소거 해제");
AudioManager.Instance.Mute(false);
}
[ContextMenu("6. Clear Cache")]
private void TestClearCache()
{
if (!IsPlaying()) return;
Debug.Log("[AudioTester] 오디오 캐시 메모리 정리 요청");
AudioManager.Instance.ClearCache();
}
// 안전 장치: 에디터 멈춰있을 때 실행 방지
private bool IsPlaying()
{
if (!Application.isPlaying)
{
Debug.LogWarning("[AudioTester] 게임 실행 중에만 테스트 가능합니다.");
return false;
}
return true;
}
}
}
Test 네임스페이스로 따로 빼놔서 테스트용 코드라는 사실을 명확히 했다.
해당 코드를 사용하기 위해서는 테스트할 씬에 게임 오브젝트를 하나 만들고 해당 컴포넌트를 붙인 다음 AudioManagerTest 컴포넌트의 스크립트 제목을 우클릭하면 테스트를 원하는 기능들이 뜨게 된다.
4. 후기
에디터 프로프래밍으로 테스트 코드를 남겨두니 확실히 나중에 동일한 기능을 테스트할 때도 편하고 이후 릴리즈 때 영향이 가지 않는 게 좋은 포인트인 것 같다. 에디터 프로그래밍에 익숙해지면 작업을 더 편하게 할 수 있을 것 같아 기대가 된다.