(C#) Coroutine

2021. 5. 31. 23:24Study/Unity

Coroutine : 일반적인 함수는 하나의 프레임에서 모두 실행되고 종료됩니다. 그렇기 때문에 FadeOut같은 여러 프레임에 걸쳐서 실행되어야하는 기능에는 어려움이 있다. Update를 사용하면 되지만 프레임 단위이므로 원하는 시간에 정확히 실행시키기 쉽지 않고, 매 프레임마다 실행되는 것을 원하지않는다면 비효율적일 것이다. Coroutine은 Unity에게서 제어권을 넘겨받아 실행하던 도중에, 함수의 끝에 도달하지 않았더라도 실행을 멈추고 제어권을 넘겨줄 수 있다(yield return <>).

 

게임을 개발하다보면 일정간격마다 또는 어떤 시점에 원하는 동작을 발생시키고 싶을 때가 있습니다.

예를 들어 1초마다 총알을 발사합니다.

또는 x축으로 원하는 만큼 움직이고 끝이 나면, y축으로 움직이고 끝이 나면, z축으로 움직이고...

이런 것들을 쉽고 효율적으로 관리해줄 수 있는 것이 Coroutine입니다.

 

그렇다면 왜 쉽고 효율적인지 알아볼까요?

예를 들어 총알을 발사하는 것을 Update를 사용한다고 합시다(또는 FixedUpdate)

그렇다면 매 프레임마다 지나간 시간을 계산하여 1초가 될때마다 (정확한 1초가 아닐 수도 있음.) 총알을 발사해야 합니다.

하나의 기능을 구현한다고 한다면 큰 문제는 없겠지만, 이런 식으로 Update에 여러가지 기능이 들어간다면?

프레임이 떨어질 수 밖에 없을 것입니다.

 

Coroutine을 사용한다면 쉽고 효율적이게 구현할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using System.Collections;
using System.Collections.Generic;
 
public class Gun
{
    IEnumerator Shot()
    {
        while(true)
        {
            //Shot Action
            yield return new WaitForSeconds(1f); //1초 대기
        }
    }
 
    public void StartShot()
    {
        StartCoroutine(Shot());    
    }
 
}
 
 
cs

코드를 보면 뭔진 몰라도 굉장히 쉽게 이해할 수 있습니다.

Shot은 계속해서 1초마다 Shot Action을 실행하는 것이고, StartCoroutine을 통해서 Shot()을 실행시키는구나.

 

하지만 Coroutine은 나와있지않고, IEnumerator, yield return, StartCoroutine 이런 것들만 있습니다.

Shot의 리턴 타입은 IEnumerator(열거자 인터페이스)입니다.

 

yield : 리턴 타입은 무조건적으로 IEnumerable, IEnumerator여야 한다.

 

IEnuermerator : Collection에서 현재 Element를 돌려주는 Current 속성과 다음 Element로 하나 전진키시는 MoveNext(), 처음 위치로 초기화 시키는 Reset() 메소드를 갖고 있다. IEnumerator 타입으로 정의한 메소드는 iterator 메소드가 된다. iterator 메소드가 호출될 때, yield return <expression>을 만나면 <expression>을 리턴하고, 그 위치가 저장된다. 그리고 다음 호출 시 저장된 위치부터 다시작된다.

 

 

Coroutine 과 Thread

Thread는 비동기적이다. 여러 Thread가 있다면, 한꺼번에 동시에 실행되는 반면 Coroutine은 특정 시점에 코루틴으로 이동하고, 그 전에 진행하던 루틴은 정지됩니다. 즉 한번에 하나만 실행됩니다. 이렇게보면 Coroutine은 일반 함수와 다를 것이 없어보이지만, 일반 함수는 return을 만나거나 함수의 마지막까지 실행되고 나서야 벗어날 수 있지만, 코루틴은 return을 만나면 함수에서 벗어나 다른 코드를 실행할 수 있습니다. 이러한 점에서 Thread 처럼 비동기적으로 보일 수 있고 context switching 이 일어나는 것이 아니기 때문에 코루틴만의 장점이 있다고 할 수 있습니다.(동기화도 필요없다) 하지만, 멀티코어 프로세서를 활용할 수 없다는 점에서 스레드보다 성능이 떨어집니다.

 

'Study > Unity' 카테고리의 다른 글

Sprite Atlas - 스프라이트 아틀라스  (1) 2021.11.16
Garbage Collection (GC)  (0) 2021.06.01
(C#) Virtual / Abstract / Interface  (0) 2021.05.31
데이터 저장하기  (0) 2020.09.19
Unity에서 GameCenter 적용시키기  (0) 2020.08.20