컴퓨터 설정까지
This commit is contained in:
154
Assets/02_Scripts/Story/ch4 scrip/SpotlightFall.cs
Normal file
154
Assets/02_Scripts/Story/ch4 scrip/SpotlightFall.cs
Normal file
@@ -0,0 +1,154 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
public class SpotlightFall : MonoBehaviour
|
||||
{
|
||||
[Header("떨어질 조명")]
|
||||
[SerializeField] private Transform spotlight;
|
||||
|
||||
[Header("도착 위치")]
|
||||
[SerializeField] private Transform fallEndPoint;
|
||||
|
||||
[Header("낙하 설정")]
|
||||
[SerializeField] private float fallDuration = 1f;
|
||||
|
||||
[Header("충돌 사운드")]
|
||||
[SerializeField] private AudioSource impactAudioSource;
|
||||
[SerializeField] private AudioClip impactSound;
|
||||
|
||||
[Range(0f, 1f)]
|
||||
[SerializeField] private float impactVolume = 1f;
|
||||
|
||||
[Tooltip("조명이 도착하기 몇 초 전에 소리를 재생할지")]
|
||||
[SerializeField] private float impactSoundLeadTime = 0.12f;
|
||||
|
||||
private Vector3 startPosition;
|
||||
private Quaternion startRotation;
|
||||
|
||||
private bool hasFallen;
|
||||
private bool isFalling;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (spotlight != null)
|
||||
{
|
||||
startPosition = spotlight.position;
|
||||
startRotation = spotlight.rotation;
|
||||
}
|
||||
}
|
||||
|
||||
public void DropSpotlight()
|
||||
{
|
||||
if (hasFallen || isFalling)
|
||||
return;
|
||||
|
||||
if (spotlight == null)
|
||||
{
|
||||
Debug.LogWarning(
|
||||
"[SpotlightFall] Spotlight가 연결되지 않았습니다."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fallEndPoint == null)
|
||||
{
|
||||
Debug.LogWarning(
|
||||
"[SpotlightFall] Fall End Point가 연결되지 않았습니다."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
hasFallen = true;
|
||||
StartCoroutine(FallRoutine());
|
||||
}
|
||||
|
||||
private IEnumerator FallRoutine()
|
||||
{
|
||||
isFalling = true;
|
||||
|
||||
Vector3 fallStartPosition = spotlight.position;
|
||||
Vector3 targetPosition = fallEndPoint.position;
|
||||
|
||||
float duration = Mathf.Max(0.01f, fallDuration);
|
||||
float elapsed = 0f;
|
||||
|
||||
bool impactSoundPlayed = false;
|
||||
|
||||
while (elapsed < duration)
|
||||
{
|
||||
elapsed += Time.deltaTime;
|
||||
|
||||
float t = Mathf.Clamp01(elapsed / duration);
|
||||
|
||||
// 처음에는 느리고 아래로 갈수록 빠르게 낙하
|
||||
float acceleratedT = t * t * t;
|
||||
|
||||
spotlight.position = Vector3.Lerp(
|
||||
fallStartPosition,
|
||||
targetPosition,
|
||||
acceleratedT
|
||||
);
|
||||
|
||||
// 완전히 도착하기 조금 전에 와장창 소리 재생
|
||||
if (!impactSoundPlayed &&
|
||||
duration - elapsed <= impactSoundLeadTime)
|
||||
{
|
||||
impactSoundPlayed = true;
|
||||
PlayImpactSound();
|
||||
}
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
// 마지막 위치 정확히 맞추기
|
||||
spotlight.position = targetPosition;
|
||||
|
||||
// Lead Time이 너무 작아 소리가 실행되지 않았을 경우 대비
|
||||
if (!impactSoundPlayed)
|
||||
{
|
||||
PlayImpactSound();
|
||||
}
|
||||
|
||||
isFalling = false;
|
||||
}
|
||||
|
||||
private void PlayImpactSound()
|
||||
{
|
||||
if (impactAudioSource == null || impactSound == null)
|
||||
return;
|
||||
|
||||
impactAudioSource.PlayOneShot(
|
||||
impactSound,
|
||||
impactVolume
|
||||
);
|
||||
}
|
||||
|
||||
public void ResetFall()
|
||||
{
|
||||
StopAllCoroutines();
|
||||
|
||||
hasFallen = false;
|
||||
isFalling = false;
|
||||
|
||||
if (impactAudioSource != null)
|
||||
impactAudioSource.Stop();
|
||||
|
||||
if (spotlight != null)
|
||||
{
|
||||
spotlight.position = startPosition;
|
||||
spotlight.rotation = startRotation;
|
||||
}
|
||||
}
|
||||
|
||||
[ContextMenu("Test Fall")]
|
||||
private void TestFall()
|
||||
{
|
||||
DropSpotlight();
|
||||
}
|
||||
|
||||
[ContextMenu("Reset Fall")]
|
||||
private void TestResetFall()
|
||||
{
|
||||
ResetFall();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user