사운드 추가 및 리소스 깨지는 문제 수정
This commit is contained in:
@@ -11,6 +11,7 @@ public class BattleManager : MonoBehaviour
|
||||
[Header("UI 연결 (선택 사항)")]
|
||||
public TMPro.TMP_InputField skillInputField; // Canvas에 배치한 텍스트 입력창
|
||||
public UnityEngine.UI.Button attackButton; // Canvas에 배치한 공격 버튼
|
||||
public TMPro.TextMeshProUGUI skillResultText; // 스킬 연성 결과 및 설명 출력용 텍스트 UI 추가 ⭐
|
||||
|
||||
private string debugInputText = "불화살을 힘차게 쏜다!"; // OnGUI 디버그용 입력 기본값
|
||||
private string statusText = "스킬을 입력하여 전투를 시작하세요.";
|
||||
@@ -34,6 +35,12 @@ public class BattleManager : MonoBehaviour
|
||||
{
|
||||
if (isAttacking) return;
|
||||
|
||||
// 버튼 클릭음 재생
|
||||
if (SoundManager.Instance != null)
|
||||
{
|
||||
SoundManager.Instance.PlayButtonClick();
|
||||
}
|
||||
|
||||
string prompt = "";
|
||||
if (skillInputField != null)
|
||||
{
|
||||
@@ -92,9 +99,21 @@ public class BattleManager : MonoBehaviour
|
||||
statusText = $"[연성 완료] 스킬: {response.name} | 피해: {response.damage}";
|
||||
Debug.Log($"[Battle] 스킬 연성 성공: {response.name} (대미지: {response.damage}) - {response.description}");
|
||||
|
||||
// AI가 연성한 최종 스킬 정보를 화면상 텍스트 UI에 실시간 갱신 출력합니다.
|
||||
if (skillResultText != null)
|
||||
{
|
||||
skillResultText.text = $"스킬 연성 성공: {response.name} (대미지: {response.damage})\n- {response.description}";
|
||||
}
|
||||
|
||||
// 2. 플레이어 공격 애니메이션 및 적 타격 처리
|
||||
if (player != null && player.hp > 0)
|
||||
{
|
||||
// 플레이어 휘두르기 공격음 재생
|
||||
if (SoundManager.Instance != null)
|
||||
{
|
||||
SoundManager.Instance.PlayAttackSwing();
|
||||
}
|
||||
|
||||
Animator pAnim = player.GetComponentInChildren<Animator>();
|
||||
if (pAnim != null)
|
||||
{
|
||||
|
||||
@@ -66,12 +66,24 @@ public class Enemy : MonoBehaviour
|
||||
{
|
||||
if (hp <= 0)
|
||||
{
|
||||
// 1. 적 전사 사망 효과음 재생
|
||||
if (SoundManager.Instance != null)
|
||||
{
|
||||
SoundManager.Instance.PlayEnemyDeath();
|
||||
}
|
||||
|
||||
// SPUM 리소스 기준 사망(4_Death) 트리거 작동
|
||||
animator.SetTrigger("4_Death");
|
||||
Debug.Log($"[Enemy] 적 {enemyName}이(가) 사망하였습니다.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 2. 적 피격 효과음 재생
|
||||
if (SoundManager.Instance != null)
|
||||
{
|
||||
SoundManager.Instance.PlayPunchHit();
|
||||
}
|
||||
|
||||
// SPUM 리소스 기준 피격(3_Damaged) 트리거 작동
|
||||
animator.SetTrigger("3_Damaged");
|
||||
}
|
||||
@@ -85,6 +97,12 @@ public class Enemy : MonoBehaviour
|
||||
|
||||
Debug.Log($"[Enemy] 적 {enemyName}이(가) 플레이어를 공격합니다! (데미지: {attackPower})");
|
||||
|
||||
// 3. 적 공격 휘두르기 효과음 재생
|
||||
if (SoundManager.Instance != null)
|
||||
{
|
||||
SoundManager.Instance.PlayAttackSwing();
|
||||
}
|
||||
|
||||
if (animator != null)
|
||||
{
|
||||
// SPUM 리소스 기준 공격(2_Attack) 트리거 작동
|
||||
|
||||
@@ -127,6 +127,12 @@ public class NPCDialogueManager : MonoBehaviour
|
||||
{
|
||||
dialogueText.text = lastDialogueText;
|
||||
}
|
||||
|
||||
// 공백 문자가 아닌 경우에만 츤데레 훈수 타자기 효과음 재생
|
||||
if (letter != ' ' && SoundManager.Instance != null)
|
||||
{
|
||||
SoundManager.Instance.PlayTyping();
|
||||
}
|
||||
|
||||
// 쉼표(,)나 마침표(.) 등 문장이 끊기는 지점에서는 살짝 더 더듬는 효과(딜레이 추가) 제공
|
||||
if (letter == ',' || letter == '.')
|
||||
|
||||
@@ -138,7 +138,15 @@ public class Player : MonoBehaviour
|
||||
return;
|
||||
}
|
||||
|
||||
InputContoller.UpdateInput(ref _inputs);
|
||||
// 배틀 스테이지 씬에서는 이동 입력을 무시하여 움직이지 못하게 차단합니다 (채팅 공격 전용)
|
||||
if (UnityEngine.SceneManagement.SceneManager.GetActiveScene().name == "battleStage")
|
||||
{
|
||||
_inputs.PlayerMove = Vector2.zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
InputContoller.UpdateInput(ref _inputs);
|
||||
}
|
||||
|
||||
// 좌우 방향 전환 (Flip)
|
||||
if (_inputs.PlayerMove.x < 0f && isFacingRight)
|
||||
@@ -175,7 +183,8 @@ public class Player : MonoBehaviour
|
||||
{
|
||||
if (rb == null) return;
|
||||
|
||||
if (hp <= 0)
|
||||
// 사망 상태이거나 배틀 스테이지 씬일 경우 움직임 강제 정지
|
||||
if (hp <= 0 || UnityEngine.SceneManagement.SceneManager.GetActiveScene().name == "battleStage")
|
||||
{
|
||||
rb.linearVelocity = new Vector2(0f, rb.linearVelocity.y);
|
||||
return;
|
||||
@@ -206,12 +215,24 @@ public class Player : MonoBehaviour
|
||||
{
|
||||
if (hp <= 0)
|
||||
{
|
||||
// 1. 플레이어 전사 사운드 재생
|
||||
if (SoundManager.Instance != null)
|
||||
{
|
||||
SoundManager.Instance.PlayPlayerDeath();
|
||||
}
|
||||
|
||||
animator.SetTrigger("4_Death");
|
||||
Debug.Log($"플레이어가 {attackerName}에 의해 사망했습니다.");
|
||||
StartCoroutine(SendDeathReport(attackerName));
|
||||
}
|
||||
else
|
||||
{
|
||||
// 2. 플레이어 피격 사운드 재생
|
||||
if (SoundManager.Instance != null)
|
||||
{
|
||||
SoundManager.Instance.PlayPunchHit();
|
||||
}
|
||||
|
||||
animator.SetTrigger("3_Damaged");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
using UnityEngine;
|
||||
|
||||
[RequireComponent(typeof(AudioSource))]
|
||||
public class SoundManager : MonoBehaviour
|
||||
{
|
||||
// 전역 어디서나 효과음을 호출할 수 있는 싱글톤 인스턴스
|
||||
public static SoundManager Instance { get; private set; }
|
||||
|
||||
[Header("효과음 오디오 클립 등록 슬롯")]
|
||||
public AudioClip buttonClickClip; // 버튼 클릭음 (button sound 1/2)
|
||||
public AudioClip attackSwingClip; // 플레이어/적 공격 휘두르기 소리
|
||||
public AudioClip punchHitClip; // 피격 타격음 (Punch Medium Big)
|
||||
public AudioClip enemyDeathClip; // 적 사망음 (monster dead)
|
||||
public AudioClip playerDeathClip; // 플레이어 사망음 (Dead)
|
||||
public AudioClip transitionClip; // 성벽 통과 씬 전환음 (go to castle background1)
|
||||
public AudioClip typingClip; // 대화창 글자 타이핑음 (button sound 1 등)
|
||||
|
||||
[Header("타자기 효과음 풀링 설정")]
|
||||
[SerializeField] private int typingPoolSize = 5; // 동시 중첩 재생 가능한 최대 채널 수
|
||||
private AudioSource[] typingAudioPool;
|
||||
private int nextPoolIndex = 0;
|
||||
|
||||
private AudioSource globalAudioSource;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
// 싱글톤 보장
|
||||
if (Instance != null && Instance != this)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
|
||||
Instance = this;
|
||||
DontDestroyOnLoad(gameObject);
|
||||
|
||||
globalAudioSource = GetComponent<AudioSource>();
|
||||
if (globalAudioSource == null)
|
||||
{
|
||||
globalAudioSource = gameObject.AddComponent<AudioSource>();
|
||||
}
|
||||
|
||||
// 시작 시 타자기 효과음용 오디오 풀 컴포넌트를 자식으로 미리 생성해 둡니다. (영구 재사용)
|
||||
InitializeTypingPool();
|
||||
}
|
||||
|
||||
// 오브젝트 가비지를 줄이기 위한 오디오 풀링 초기화
|
||||
private void InitializeTypingPool()
|
||||
{
|
||||
typingAudioPool = new AudioSource[typingPoolSize];
|
||||
for (int i = 0; i < typingPoolSize; i++)
|
||||
{
|
||||
GameObject child = new GameObject($"TypingAudioChannel_{i}");
|
||||
child.transform.SetParent(this.transform); // SoundManager 자식으로 묶어 구조 정돈
|
||||
|
||||
AudioSource source = child.AddComponent<AudioSource>();
|
||||
source.playOnAwake = false;
|
||||
source.loop = false;
|
||||
typingAudioPool[i] = source;
|
||||
}
|
||||
}
|
||||
|
||||
// 기본 단발성 효과음 재생 메서드
|
||||
public void PlayOneShot(AudioClip clip, float volume = 1f)
|
||||
{
|
||||
if (clip != null && globalAudioSource != null)
|
||||
{
|
||||
globalAudioSource.PlayOneShot(clip, volume);
|
||||
}
|
||||
}
|
||||
|
||||
// 편리한 인게임 사운드 트리거 래퍼들
|
||||
public void PlayButtonClick() => PlayOneShot(buttonClickClip, 0.7f);
|
||||
public void PlayAttackSwing() => PlayOneShot(attackSwingClip, 0.85f);
|
||||
public void PlayPunchHit() => PlayOneShot(punchHitClip, 0.95f);
|
||||
public void PlayEnemyDeath() => PlayOneShot(enemyDeathClip, 1.0f);
|
||||
public void PlayPlayerDeath() => PlayOneShot(playerDeathClip, 1.0f);
|
||||
public void PlayTransition() => PlayOneShot(transitionClip, 0.9f);
|
||||
|
||||
// 타자기 출력 연출 효과음 (풀링 및 피치 벤딩 결합)
|
||||
public void PlayTyping()
|
||||
{
|
||||
if (typingClip == null || typingAudioPool == null || typingAudioPool.Length == 0) return;
|
||||
|
||||
// 순환 순서 인덱스의 오디오 채널을 하나 획득합니다.
|
||||
AudioSource channel = typingAudioPool[nextPoolIndex];
|
||||
nextPoolIndex = (nextPoolIndex + 1) % typingPoolSize;
|
||||
|
||||
if (channel != null)
|
||||
{
|
||||
channel.clip = typingClip;
|
||||
channel.volume = 0.22f; // 음질 중첩을 고려해 볼륨 세부 튜닝
|
||||
channel.pitch = Random.Range(0.85f, 1.15f); // 미세 피치 조절로 기계음 최소화
|
||||
channel.Play();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 99e32a34df5b44d91a7f5280093cd383
|
||||
@@ -36,6 +36,12 @@ public class WallTransition : MonoBehaviour
|
||||
Debug.LogWarning("[Transition] 씬에 GameManager 싱글톤 오브젝트가 존재하지 않아 플레이어 정보 임시 세이브를 스킵합니다.");
|
||||
}
|
||||
|
||||
// 성벽 통과/씬 전환 효과음 재생
|
||||
if (SoundManager.Instance != null)
|
||||
{
|
||||
SoundManager.Instance.PlayTransition();
|
||||
}
|
||||
|
||||
// 2. 유니티 씬 매니저를 통해 목표 씬(battleStage)을 즉시 로드합니다.
|
||||
Debug.Log($"[Transition] {targetSceneName} 씬으로 화면을 전환합니다.");
|
||||
SceneManager.LoadScene(targetSceneName);
|
||||
|
||||
Reference in New Issue
Block a user