using System.Collections; using UnityEngine; using UnityEngine.XR.Interaction.Toolkit; using UnityEngine.XR.Interaction.Toolkit.Interactables; public class SteeringKeyGrabMusic : MonoBehaviour { [Header("References")] [SerializeField] private XRGrabInteractable grabInteractable; [SerializeField] private AudioSource audioSource; [Header("Playback")] [SerializeField] private bool playOnGrab = true; [SerializeField] private bool stopOnRelease = true; [Tooltip("키를 잡았을 때 음악을 처음부터 다시 재생할지 여부입니다.")] [SerializeField] private bool restartFromBeginningOnGrab = false; [Header("Fade")] [SerializeField] private bool useFade = true; [SerializeField] private float fadeInDuration = 0.4f; [SerializeField] private float fadeOutDuration = 0.5f; [Range(0f, 1f)] [SerializeField] private float targetVolume = 1f; [Header("Debug")] [SerializeField] private bool showDebugLog = true; private Coroutine fadeRoutine; private bool isGrabbed; private void Awake() { if (grabInteractable == null) grabInteractable = GetComponentInChildren(true); if (audioSource == null) audioSource = GetComponent(); if (audioSource != null) { audioSource.playOnAwake = false; audioSource.loop = true; if (useFade) audioSource.volume = 0f; else audioSource.volume = targetVolume; } } private void OnEnable() { if (grabInteractable != null) { grabInteractable.selectEntered.AddListener(OnKeyGrabbed); grabInteractable.selectExited.AddListener(OnKeyReleased); } } private void OnDisable() { if (grabInteractable != null) { grabInteractable.selectEntered.RemoveListener(OnKeyGrabbed); grabInteractable.selectExited.RemoveListener(OnKeyReleased); } } private void OnKeyGrabbed(SelectEnterEventArgs args) { isGrabbed = true; if (!playOnGrab) return; if (audioSource == null) { if (showDebugLog) Debug.LogWarning("[SteeringKeyGrabMusic] AudioSource가 연결되지 않았습니다.", this); return; } if (restartFromBeginningOnGrab) audioSource.time = 0f; if (!audioSource.isPlaying) audioSource.Play(); if (useFade) StartFade(targetVolume, fadeInDuration); else audioSource.volume = targetVolume; if (showDebugLog) Debug.Log("[SteeringKeyGrabMusic] 키 잡음. 음악 재생.", this); } private void OnKeyReleased(SelectExitEventArgs args) { isGrabbed = false; if (!stopOnRelease) return; if (audioSource == null) return; if (useFade) StartFade(0f, fadeOutDuration, stopAfterFade: true); else audioSource.Stop(); if (showDebugLog) Debug.Log("[SteeringKeyGrabMusic] 키 놓음. 음악 정지.", this); } private void StartFade(float target, float duration, bool stopAfterFade = false) { if (fadeRoutine != null) StopCoroutine(fadeRoutine); fadeRoutine = StartCoroutine(FadeRoutine(target, duration, stopAfterFade)); } private IEnumerator FadeRoutine(float target, float duration, bool stopAfterFade) { if (audioSource == null) yield break; float startVolume = audioSource.volume; float timer = 0f; float safeDuration = Mathf.Max(0.01f, duration); while (timer < safeDuration) { timer += Time.deltaTime; float t = Mathf.Clamp01(timer / safeDuration); float smoothT = t * t * (3f - 2f * t); audioSource.volume = Mathf.Lerp(startVolume, target, smoothT); yield return null; } audioSource.volume = target; if (stopAfterFade && !isGrabbed) { audioSource.Stop(); } fadeRoutine = null; } }