상세 컨텐츠

본문 제목

#10. 코루틴(Coroutine)

유니티 학습/세미나 자료

by 남민우_ 2024. 7. 31. 22:49

본문

1. 코루틴이란?

여러 코드를 순차적 방식이 아닌 병렬적 방식으로 처리한다.

더보기

순차 : 병렬

1. 순차

위에서 아래로, 혹은 아래에서 위로 등 정해진 순서에 따라 진행되는 것.

 + 프로그래밍의 기본적인 순서는 위에서 아래로 진행되는 순차적 방식을 따른다.

 

2. 병렬

한 동작에 한 가지 일을 하는 것이 아니라, 여러가지 일을 동시에 진행하는 것

기본적으로 모든 코드 처리 순서는 위에서 아래로 진행된다.

1 -> 2, 2 -> 3 의 순서로 코드가 진행된다.

 

코루틴은 이러한 순차적 처리 방식이 아닌, 병렬적 처리 방식으로 진행되는 코드를 말한다.

 

2. 예제 실습 - FadeIn/FadeOut 연출

화면이 점차 밝아지는 FadeIn, 점차 어두워지는 FadeOut 을 연출해보겠다.

이 연출은 화면을 전부 덮는 이미지를 만들어두고 이미지의 투명값을 조절하여 만들 수 있다.

 

1. 화면을 덮을 이미지 생성

Hierarchy 창의 + 버튼을 통해서 접근한다
이전에 만든 Canvas에서 우클릭, Image를 생성한다
만든 Image의 Inspector 창에서 조절한다

 

결과

Scene 창은 레벨 전체를 보여주기 때문에 Canavas 뒤의 공간도 같이 나온다

실제 플레이되는 Game 창을 통해 확인할 수 있듯이, 화면 전체가 생성한 이미지로 덮인 모습이다.

 

이제 이 이미지의 투명도(알파값)을 조절하여 Fade 연출을 만들 수 있다.

 

코드

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Fade : MonoBehaviour
{
    public Image fadeImage;
    // Start is called before the first frame update
    void Start()
    {
        FadeIn();
    }

    void FadeIn()
    {
        Color startColor = fadeImage.color;
        for(int i =0; i<100; i++)
        {
            startColor.a -= 0.01f;
            fadeImage.color = startColor;
        }
    }
}
더보기

using UnityEngine.UI

유니티에서의 Image, Color 선언 등을 사용하기 위해 추가한 헤더이다.

UI와 관련된 문법들을 포함하고 있다.

 

+ Color.a 에서의 'a' 는 알파값을 의미한다 ( R G B A 에서의 A )

결과

플레이를 하자마자 바로 사진과 같은 상태가 된다

이미지가 투명해지기는 하지만, 우리가 원하는 연출 효과는 아니다.

Why? 컴퓨터의 연산 속도는 매우 빠르게 진행된다.

코드 상, 알파값을 0.01f씩 총 100번 낮추는데 이 연산 속도가 매우 빨라서 우리 눈에는 찰나의 순간으로 보여

플레이 하자마자 바로 투명한 이미지가 보이는 것이다.

 

그럼 우리는 어떻게 해야할까?

바로 연산 진행 사이에 대기시간을 추가하는 것이다.

 

3. 코루틴의 기능

 3-1. 대기시간

일반적인 코드 진행은 순차적으로 + 쉬지 않고 진행된다.

코루틴은, 코드 사이에 대기 시간을 넣어 코드의 진행에 딜레이를 줄 수 있다.

 

코드 구성

'IEnumerator' 라는 타입과, 'yield return' 의 반환문 사용

1. IEnumerator

함수의 이름 앞에 타입으로서 사용 => void, int 와 같은 함수의 타입을 대체한다.

public / private 같은 범위 지정자를 쓴다면, 다른 경우와 마찬가지로 타입의 앞에 사용한다

public IEnumerator FadeIn()
{
	yield return null;
}

 

2. yield return

코루틴 함수에서만 사용하는 특별한 return 문

코루틴을 실행시키는 도중, 'yield return'을 만나면 뒤의 반환값 만큼의 대기시간을 가진다

 ex) yield return 0.5f 등. 예시와 같이 null값도 가능하다

 

 

진행 방식

 

핵심은,

1. yield return 을 통해 대기하는 동안 코루틴은 정지하지만 다른 코드들은 진행된다

 => 병렬적 처리 방식

2. yield return 을 만난 위치를 기억하여, 대기 시간이 종료된 후 해당 위치에서 코드가 이어서 진행된다.

의 2가지이다.

 

코드

public class Fade : MonoBehaviour
{
    public Image fadeImage;
    // Start is called before the first frame update
    void Start()
    {
        StartCoroutine(FadeIn());
    }

    IEnumerator FadeIn()
    {
        Color startColor = fadeImage.color;
        for (int i = 0; i < 100; i++)
        {
            startColor.a -= 0.01f;
            fadeImage.color = startColor; 
            yield return new WaitForSeconds(0.01f);
        }
    }
}

이 코드를 통해 알아야 할 점으로는

 

1. yield return 을 통해 대기시간 부여 => new WaitForSeconds(0.01f) / 0.01초만큼 대기

2. 코루틴 함수는 함수 호출 시 함수의 이름만 사용하는 것이 아니라, "StartCoroutine( ~ )" 함수를 사용하여 호출한다

 : String 형식과 함수 호출 형식 모두 사용 가능

 

 

결과

이미지 형식이라 진행 과정이 보이진 않지만, 점차 화면이 밝아진다

정상적으로 작동한다

 

더보기

StartCoroutine에 대해서

: 함수의 안에  코루틴 함수를 호출하고, 호출 방식은 string 형식과 함수 형식 모두 가능하다

 

ex1) StartCoroutine("FadeIn") : String 타입

 : 코루틴 시작 후 인위적으로 함수 중단이 가능하다

 

ex2) StartCoroutine(FadeIn()) : 함수 타입

 : 성능은 string 형식보다 뛰어나지만 인위적으로 중단이 불가능하다

 

+ 필자가 직접 돌려본 결과로는 둘 다 중단이 가능하다. 따라서 함수 형식을 사용하는게 기능 상 더 좋을 것으로 예상됨.

 

+ 인위적 중단이란? : StopCoroutine( ~ )

코루틴이 동작하는 도중, StopCoroutine 함수 호출을 통해 코루틴의 동작을 중단할 수 있다.

 

 3-2. 병렬 처리

모든 코드들은 위에서 아래로 순차적으로 진행되고, 이전 코드가 끝나지 않으면 다음 코드가 실행되지 않는다.

Start() 에서 Func1 과 Func2 를 순차적으로 호출, 실행한다

Function1의 코드가 종료되기 전에 Function2가 시작되지 않는다.

하지만 코루틴은 조금 다르다.

 

코드

public class BeCoroutine : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        StartCoroutine(Function1());
        StartCoroutine(Function2());
        Debug.Log("모든 함수 종료");
    }

    IEnumerator Function1()
    {
        Debug.Log("함수1 시작");
        yield return new WaitForSeconds(3f);
        Debug.Log("함수1 종료");
    }

    IEnumerator Function2() 
    {
        Debug.Log("함수2 시작");
        yield return new WaitForSeconds(5f);
        Debug.Log("함수2 종료");
    }
}

코루틴의 대한 이해도 없이 이 코드를 봤을 때, "함수 2 종료" 디버그 로그가 출력될 때 까지 8f의 시간이 걸릴 것 같다.

 

실행 결과

총 5f의 시간이 소요되었다

시작과 동시에 Function1 과 Function2가 실행되고, "모든 함수 종료" 라는 Start() 함수의 디버그 로그가 출력된다.

그 후 3f의 시간 후 Function1 이 종료되고, 동시에 5f의 시간 후 Function2 가 종료된다.

 

이러한 현상을 우리는 "비동기방식(ASyne)" 이라고 말한다.

 

  3-2-1. 비동기방식 : ASyne

A, B, C의 시작과 종료 타이밍을 그림으로 표현한 모습

A가 시작되고 이후에 B가 시작되는데 이 때, A와 B가 공통적으로 진행되는 순간이 존재한다.

C의 경우도 마찬가지다.

 

이처럼 코드가 공통적으로 진행되는 순간,

코드를 병렬적으로 처리할 수 있게 하는 함수가 바로 코루틴 함수이다.

파란 네모의 구간에는 A, B, C가 동시에 작동한다

이 사진처럼 한 시점에 여러 작업이 동시에 처리되는 구간이 존재하고, 이러한 처리 방식을 이용해서 우리는

멀티 스레드 프로그래밍이 가능해진다.

 

더보기

코루틴과 반대되는 개념으로 '동기방식(Syne)'이 있다.

A가 종료되고 B가 시작, B가 종료되고 C가 시작한다

순차적이고, 직렬적인 방식이라고 볼 수 있다.


+ 코루틴의 활용 : 반복문

만약 일반 함수를 While(1)과 같은 반복문을 통해 사용한다면?

흔히 말하는 '무한루프' 에 빠져 컴퓨터 과부하로 에러가 발생하기 쉬워진다.

 

하지만 코루틴 함수는 yield return 을 통해 함수 자체에 대기시간을 주기 때문에 과부하의 여지가 없고, 그에 따라 에러가 발생하지 않는다

=> 코루틴과 무한 루프는 매우 좋은 조합으로 활용이 가능하다.

'유니티 학습 > 세미나 자료' 카테고리의 다른 글

#12. 상속 심화  (0) 2024.08.02
#11. 레이캐스트(RayCast)  (0) 2024.08.01
#9. 싱글톤(Singleton)  (0) 2024.07.31
#8. 리스트(List)  (0) 2024.07.30
#7. 정적 변수/함수(Static)  (0) 2024.07.29

관련글 더보기