Projext/Assets/Scripts/Player/Sound/PlayerSoundFX.cs
2026-02-27 09:44:52 +09:00

139 lines
6.9 KiB
C#

using UnityEngine; // 유니티 기능을 불러올거에요 -> UnityEngine을
/// <summary>
/// 플레이어 사운드 관리
/// 플레이어 오브젝트에 부착 — AudioSource 자동 추가
/// 애니메이션 이벤트 또는 코드에서 호출
/// </summary>
[RequireComponent(typeof(AudioSource))] // 컴포넌트를 강제 추가할거에요 -> AudioSource를
public class PlayerSoundFX : MonoBehaviour // 클래스를 선언할거에요 -> 플레이어 사운드를
{
[Header("--- 활 사운드 ---")] // 인스펙터 제목을 달거에요 -> 활 사운드를
[SerializeField] private AudioClip bow_draw; // 변수를 선언할거에요 -> 활 시위 당기기 소리를
[SerializeField] private AudioClip bow_charge_loop; // 변수를 선언할거에요 -> 차징 루프 소리를
[SerializeField] private AudioClip bow_release; // 변수를 선언할거에요 -> 화살 발사 소리를
[Header("--- 화살 명중 ---")] // 인스펙터 제목을 달거에요 -> 명중 사운드를
[SerializeField] private AudioClip arrow_hit_flesh; // 변수를 선언할거에요 -> 적 명중 소리를
[SerializeField] private AudioClip arrow_hit_wall; // 변수를 선언할거에요 -> 벽 명중 소리를
[Header("--- 이동 사운드 ---")] // 인스펙터 제목을 달거에요 -> 이동 사운드를
[SerializeField] private AudioClip[] player_footsteps; // 배열을 선언할거에요 -> 발걸음 소리들을 (2~3개 변형)
[SerializeField] private AudioClip player_dash; // 변수를 선언할거에요 -> 대시 소리를
[Header("--- 피격/사망 ---")] // 인스펙터 제목을 달거에요 -> 피격 사운드를
[SerializeField] private AudioClip player_hit; // 변수를 선언할거에요 -> 피격 소리를
[SerializeField] private AudioClip player_death; // 변수를 선언할거에요 -> 사망 소리를
[Header("--- 볼륨 ---")] // 인스펙터 제목을 달거에요 -> 볼륨 설정을
[Range(0f, 1f)]
[SerializeField] private float sfxVolume = 0.6f; // 변수를 선언할거에요 -> 효과음 볼륨을
[Range(0f, 1f)]
[SerializeField] private float footstepVolume = 0.3f; // 변수를 선언할거에요 -> 발걸음 볼륨을
private AudioSource _audioSource; // 변수를 선언할거에요 -> 오디오 소스를
private AudioSource _loopSource; // 변수를 선언할거에요 -> 루프 전용 소스를 (차징 루프용)
private void Awake() // 함수를 실행할거에요 -> 초기화를
{
_audioSource = GetComponent<AudioSource>(); // 가져올거에요 -> 기본 오디오 소스를
_audioSource.playOnAwake = false; // 설정할거에요 -> 자동 재생 끄기로
// 루프 전용 AudioSource 추가 (차징 소리가 원샷과 겹치지 않게)
_loopSource = gameObject.AddComponent<AudioSource>(); // 추가할거에요 -> 루프 전용 채널을
_loopSource.loop = true; // 설정할거에요 -> 루프로
_loopSource.playOnAwake = false; // 설정할거에요 -> 자동 재생 끄기로
_loopSource.volume = sfxVolume * 0.7f; // 설정할거에요 -> 약간 작은 볼륨으로
}
// ============================================
// 활 사운드 — PlayerAttack에서 호출
// ============================================
/// <summary> 차징 시작 시 호출 (PlayerAttack.StartCharging) </summary>
public void PlayBowDraw() // 함수를 선언할거에요 -> 활 당기기 소리를
{
PlayOneShot(bow_draw); // 재생할거에요 -> 시위 당기기 소리를
// 차징 루프 시작
if (bow_charge_loop != null) // 조건이 맞으면 실행할거에요 -> 루프 클립이 있다면
{
_loopSource.clip = bow_charge_loop; // 설정할거에요 -> 루프 클립을
_loopSource.Play(); // 재생할거에요 -> 루프를
}
}
/// <summary> 발사 시 호출 (PlayerAttack.OnShootArrow) </summary>
public void PlayBowRelease() // 함수를 선언할거에요 -> 화살 발사 소리를
{
StopChargeLoop(); // 실행할거에요 -> 차징 루프 정지를
PlayOneShot(bow_release); // 재생할거에요 -> 발사 소리를
}
/// <summary> 차징 취소 시 호출 (PlayerAttack.CancelCharging) </summary>
public void StopChargeLoop() // 함수를 선언할거에요 -> 차징 루프 정지를
{
if (_loopSource.isPlaying) _loopSource.Stop(); // 정지할거에요 -> 루프를
}
// ============================================
// 화살 명중 — Arrow.cs HandleHit에서 호출
// ============================================
/// <summary> 적 명중 시 </summary>
public void PlayArrowHitFlesh(Vector3 position) // 함수를 선언할거에요 -> 적 명중 소리를
{
if (arrow_hit_flesh != null) // 조건이 맞으면 실행할거에요 -> 클립이 있다면
AudioSource.PlayClipAtPoint(arrow_hit_flesh, position, sfxVolume); // 재생할거에요 -> 명중 위치에서
}
/// <summary> 벽/바닥 명중 시 </summary>
public void PlayArrowHitWall(Vector3 position) // 함수를 선언할거에요 -> 벽 명중 소리를
{
if (arrow_hit_wall != null) // 조건이 맞으면 실행할거에요 -> 클립이 있다면
AudioSource.PlayClipAtPoint(arrow_hit_wall, position, sfxVolume); // 재생할거에요 -> 명중 위치에서
}
// ============================================
// 발걸음 — 애니메이션 이벤트에서 호출
// ============================================
// 발소리는 PlayerFootstep 컴포넌트에서 처리
// 애니메이션 이벤트 함수명: OnFootstep → PlayerFootstep.OnFootstep()
// ============================================
// 대시 — PlayerMovement.DashRoutine에서 호출
// ============================================
public void PlayDash() // 함수를 선언할거에요 -> 대시 소리를
{
PlayOneShot(player_dash); // 재생할거에요 -> 대시 소리를
}
// ============================================
// 피격/사망 — PlayerHealth에서 호출
// ============================================
public void PlayPlayerHit() // 함수를 선언할거에요 -> 피격 소리를
{
PlayOneShot(player_hit); // 재생할거에요 -> 피격 소리를
}
public void PlayPlayerDeath() // 함수를 선언할거에요 -> 사망 소리를
{
PlayOneShot(player_death); // 재생할거에요 -> 사망 소리를
}
// ============================================
// 유틸리티
// ============================================
private void PlayOneShot(AudioClip clip) // 함수를 선언할거에요 -> 원샷 재생 헬퍼를
{
if (clip != null && _audioSource != null) // 조건이 맞으면 실행할거에요 -> 둘 다 있다면
_audioSource.PlayOneShot(clip, sfxVolume); // 재생할거에요 -> 효과음을
}
}