Files
WhaleAdventure_VR/Assets/02_Scripts/Cave/SteeringKeyGrabMusic.cs
2026-06-24 14:40:39 +09:00

159 lines
4.2 KiB
C#

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<XRGrabInteractable>(true);
if (audioSource == null)
audioSource = GetComponent<AudioSource>();
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;
}
}