159 lines
4.2 KiB
C#
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;
|
|
}
|
|
}
|