카드 뒤집기 이펙트 구현 및 Coroutine 활용
카드 뒤집기 관련 이펙트를 구현하기 위해 Transform을 사용하여 회전 및 크기 조정을 시도했다. 이때, 변경에 필요한 시간을 Time.deltaTime을 사용해 일정 시간 동안 부드럽게 변경되도록 구현했다. 그러나 코드 상으로는 시간 내에 회전이 완료되어야 했지만, 회전이 중간에 멈추는 현상이 발생했다.
문제 원인
이 문제는 Unity에서 제공하는 Time.deltaTime이 항상 일정하지 않기 때문에 발생했다. Time.deltaTime은 프레임 간의 시간 차이를 반환하므로, 프레임률(FPS)이 불안정한 경우 회전 속도가 일정하지 않을 수 있다. 특히 저사양 기기나 복잡한 씬에서는 프레임률이 떨어져 이 문제가 더 두드러질 수 있다.
해결 방법: Coroutine 도입
이 문제를 해결하기 위해 Coroutine을 도입했다. Coroutine은 함수가 종료되지 않는 한 반복적으로 실행되는 방식으로, 시간 기반의 작업을 보다 정확하게 제어할 수 있다.
Coroutine 사용법
Coroutine은 StartCoroutine 함수를 호출하여 실행하며, 인자로 IEnumerator 형 함수를 전달한다.
Coroutine 내부에서는 yield return을 사용하여 실행을 일시 중지하거나 특정 조건까지 대기할 수 있다.
회전 이펙트 구현
회전은 일정 시간 동안 천천히 이루어져야 하므로, WaitForSeconds를 사용하여 일정 시간 동안 Coroutine을 일시 중지했다. 회전량을 확인하기 위해 오일러 각을 기준으로 회전값을 비교했으며, float 값의 비교는 정확하지 않을 수 있으므로, Mathf.Approximately를 사용하거나 int형으로 변환하여 비교했다.
Coroutine의 동작 원리
Coroutine은 Unity의 메인 스레드에서 실행되며, 일련의 작업을 순차적으로 처리한다. Coroutine은 yield return을 통해 실행을 일시 중지하고, 특정 조건이 충족되면 다시 실행을 재개한다.
주요 yield return 타입
yield return new WaitForSeconds(3.0f); // 3초 동안 대기한 후 다음 코드를 실행한다.
yield return null; // 다음 프레임까지 대기한다.
public class CardFlip : MonoBehaviour
{
public float flipDuration = 1.0f; // 회전에 걸리는 시간
public float targetRotation = 180f; // 목표 회전 각도
private bool isFlipping = false;
void Update()
{
if (Input.GetMouseButtonDown(0) && !isFlipping)
{
StartCoroutine(FlipCard());
}
}
IEnumerator FlipCard()
{
isFlipping = true;
float elapsedTime = 0f;
Quaternion startRotation = transform.rotation;
Quaternion targetRotation = Quaternion.Euler(0, this.targetRotation, 0);
while (elapsedTime < flipDuration)
{
transform.rotation = Quaternion.Slerp(startRotation, targetRotation, elapsedTime / flipDuration);
elapsedTime += Time.deltaTime;
yield return null; // 다음 프레임까지 대기
}
transform.rotation = targetRotation; // 정확한 각도로 설정
isFlipping = false;
}
}
FlipCard Coroutine 에 대한 설명
1. elapsedTime을 사용해 경과 시간을 계산
2. Quaternion.Slerp를 사용해 시작 각도에서 목표 각도까지 부드럽게 회전함.
3. yield return null을 사용해 매 프레임마다 회전을 업데이트
4. 회전 완료 보정 - Coroutine이 종료될 때 정확한 목표 각도로 설정하여 오차를 보정한다.
5. isFlipping 플래그 - 중복 실행을 방지하기 위해 isFlipping 플래그를 사용합니다.
결론
Time.deltaTime을 사용한 회전은 프레임률에 따라 불안정할 수 있으므로, Coroutine을 사용해 시간 기반의 작업을 정확하게 제어할 수 있다.