| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 |
- Unity
- 독서
- C++
- multi-thread
- System Programming
- Network Programming
- BOJ
- Data Structure
- git
- Online Judge
- PS
- Toy Project
- c#
- Today
- Total
I'm FanJae.
[20260528] Unity 정리 ( Coroutine ) 본문
1. 정의
- 코루틴은 실행 도중에 잠시 멈췄다가, 특정 조건이 만족되면 중단된 지점부터 다시 실행되는 함수다. 일반 함수는 호출되면 한 프레임 안에서 로직을 끝내고 반환된다. 하지만 코루틴은 중간에 yield return 을 사용해서 실행을 잠시 멈출 수 있다.
void Test()
{
Debug.Log("시작");
Debug.Log("끝");
}
- 하지만 코루틴은 중간에 yield return을 사용해서 실행을 잠시 멈출 수 있다.
IEnumerator TestCo()
{
Debug.Log("시작");
yield return new WaitForSeconds(1.0f);
Debug.Log("1초 뒤 실행");
}
- 코루틴은 여러 프레임에 걸쳐 동작을 처리할 때 유용하다고 설명한다. StartCoroutine 은 첫 번째 yield return 지점까지 실행되고, 이후 조건에 따라 이어서 실행되는 특징을 가지고 있다.
2. 필요한 이유
- 게임에서는 특정 작업을 바로 실행하지 않고, 일정 시간 뒤에 실행해야 하는 경우가 많다.
1초마다 색상 변경
2초 뒤에 메시지 출력
몇 프레임에 걸쳐 오브젝트 이동
스킬 캐스팅 후 쿨타임 진행
- 이런 처리를 전부 Update() 에서 만들 수도 있다.
timer += Time.deltaTime;
if (timer >= 1.0f)
{
Debug.Log("1초 지남");
timer = 0.0f;
}
- 하지만 조건이 많아지면 Update() 내부가 복잡해진다.
- 코루틴을 사용하면 기다렸다가 실행한다는 흐름을 코드상에서 더 직관적으로 표현할 수 있다.
3. 기본 구조
- 코루틴은 반환형으로 IEnumerator를 사용한다.
IEnumerator CoroutineName()
{
yield return 대기조건;
}
- 실행할 때는 StartCoroutine()을 사용한다.
StartCoroutine(CoroutineName());
void Start()
{
StartCoroutine(PrintNumberCo());
}
IEnumerator PrintNumberCo()
{
for (int i = 0; i < 5; i++)
{
Debug.Log(i);
yield return null;
}
}
- yield return null은 다음 프레임까지 대기한다.
- 즉, 위 코드는 숫자를 한 프레임마다 하나씩 출력한다.
4. 자주 사용하는 yield return
yield return null - 다음 프레임까지 대기
yield return new WaitForSeconds(1.0f) - 게임 시간 기준 1초대기
yield return new WaitForSEcondsRealtime(1.0f) - 실제 시간 기준 1초 대기
yield return new WaitForFixedUpdate() - 다음 FixedUpdate 타이밍까지 대기
yield return StartCoroutine(OtherCo()) - 다른 코루틴이 끝날 때까지 대기
yield break - 코루틴 종료
- WaitForSeconds는 Time.timeScale의 영향을 받는 시간 대기 방식이다. 반대로 WaitForSecondsRealtime은 실제 시간 기준 대기에 사용한다.
5. 일정 시간마다 반복 실행
IEnumerator PrintDelayCo()
{
for (int i = 0; i < 3; i++)
{
Debug.Log(i);
yield return new WaitForSeconds(1.0f);
}
}
- 이 코드는 1초 간격으로 숫자를 출력한다.
- Update()로 작성하면 타이머 변수와 조건문이 필요하지만, 코루틴에서는 출력 → 1초 대기 → 출력 흐름이 그대로 보인다.
6. 다른 코루틴이 끝날 때까지 대기
- 코루틴 안에서 다른 코루틴을 실행하고, 그 코루틴이 끝날 때까지 기다릴 수 있다.
IEnumerator MainRoutineCo()
{
Debug.Log("코루틴 첫번째");
yield return StartCoroutine(WaitPrintCo());
Debug.Log("모든 루틴 완료");
}
IEnumerator WaitPrintCo()
{
yield return new WaitForSeconds(2.0f);
Debug.Log("딜레이 완료");
}
- 실행 순서는 다음과 같다.
코루틴 첫번째
2초 대기
딜레이 완료
모든 루틴 완료
- StartCoroutine의 반환값을 yield return하면 해당 코루틴이 끝날 때까지 기다릴 수 있다.
7. 프레임 단위 이동 처리
- 코루틴은 오브젝트를 여러 프레임에 걸쳐 이동시킬 때도 사용할 수 있다.
IEnumerator MoveCube()
{
Vector3 startPos = transform.position;
Vector3 targetPos = startPos + Vector3.right * 5.0f;
float duration = 3.0f;
float elapsedTime = 0.0f;
while (elapsedTime < duration)
{
transform.position = Vector3.Lerp(startPos,targetPos,
elapsedTime / duration);
elapsedTime += Time.deltaTime;
yield return null;
}
transform.position = targetPos;
}
- 여기서 핵심은 이 부분이다.
elapsedTime/duration
- 예를 들어 전체 시간이 3초이고, 현재 1.5초가 지났다고 가정한다.
1.5f / 3.0f = 0.5f
- 즉, 이동이 50% 진행된 상태가 된다.
8. WaitForSeconds 캐싱
- 반복문 안에서 new WaitForSeconds() 를 계속 생성하는 경우가 있다.
while (true)
{
yield return new WaitForSeconds(1.0f);
}
- 이 방식이 항상 문제라고 단정할 필요는 없지만, 매우 자주 반복되는 구조라면 대기 객체를 미리 만들어두는 방식을 고려할 수 있다.
private WaitForSeconds wait;
void Start()
{
wait = new WaitForSeconds(1.0f);
StartCoroutine(ChangeColorCo());
}
IEnumerator ChangeColorCo()
{
while (true)
{
yield return wait;
}
9. 주의점
- 코루틴을 Update() 에서 아무 조건 없이 호출하면 안 된다.
void Update()
{
StartCoroutine(PrintDelayCo());
}
- 이렇게 작성하면 매 프레임마다 새로운 코루틴이 계속 시작된다.
- 즉, 코루틴이 하나만 실행되는 것이 아니라 여러 개가 누적 실행될 수 있다.
private Coroutine routine;
void Update()
{
if (Input.GetKeyDown(KeyCode.Space) && routine == null)
{
routine = StartCoroutine(PrintDelayCo());
}
}
- 코루틴이 끝나면 다시 실행 가능하도록 처리를 해야 한다.
IEnumerator PrintDelayCo()
{
yield return new WaitForSeconds(1.0f);
Debug.Log("완료");
routine = null;
}
10. OnDisable에서 정리하기
- 오브젝트가 비활성화되었을 때 실행 중인 코루틴을 정리해야 하는 경우도 있다.
private Coroutine routine;
void OnDisable()
{
if (routine != null)
{
StopCoroutine(routine);
routine = null;
}
}
- 특히 UI, 스킬 쿨타임, 반복 색상 변경처럼 상태가 남을 수 있는 기능은 OnDisable() 에서 초기화해주는 편이 안전하다.
11. 정리
- 코루틴은 일정 시간 대기, 반복 실행, 순차 실행, 프레임 단위 처리를 간단하게 작성할 수 있게 해준다.
- Update()에서 타이머와 조건문으로 처리할 수도 있지만, 코루틴을 사용하면 시간 흐름이 코드에 더 직접적으로 드러난다.
- 다만 코루틴도 남발하면 문제가 생긴다. 특히 Update()에서 매 프레임 StartCoroutine()을 호출하면 여러 코루틴이 동시에 쌓일 수 있다.
- 따라서 코루틴은 보통 다음과 같이 사용하는 것이 좋다.
1. Start나 특정 이벤트에서 실행
2. 반복 실행이 필요하면 while, for와 yield 사용
3. Update에서 호출해야 한다면 조건문으로 중복 실행 방지
4. 필요하면 Coroutine 변수를 저장해서 중지 가능하게 만들기
5. 오브젝트 비활성화 시 OnDisable에서 정리
'Unity > Unity 초격차캠프' 카테고리의 다른 글
| [20260529] Unity 정리 ( 싱글톤 패턴, Singleton Pattern ) (0) | 2026.05.29 |
|---|---|
| [20260528] Unity 정리 ( Find 계열 ) (0) | 2026.05.28 |
| [20260527] Unity 정리 ( UI Canvas ) (0) | 2026.05.27 |
| [20260527] Unity 정리 ( Overlap 계열, Check 계열 ) (0) | 2026.05.27 |
| [20260527] Unity 정리 ( Unity Raycast 응용 : LayerMask, Tag, Raycast를 이용한 상호작용 ) (0) | 2026.05.27 |