여러 코드를 순차적 방식이 아닌 병렬적 방식으로 처리한다.
순차 : 병렬
1. 순차
위에서 아래로, 혹은 아래에서 위로 등 정해진 순서에 따라 진행되는 것.
+ 프로그래밍의 기본적인 순서는 위에서 아래로 진행되는 순차적 방식을 따른다.
2. 병렬
한 동작에 한 가지 일을 하는 것이 아니라, 여러가지 일을 동시에 진행하는 것
기본적으로 모든 코드 처리 순서는 위에서 아래로 진행된다.
코루틴은 이러한 순차적 처리 방식이 아닌, 병렬적 처리 방식으로 진행되는 코드를 말한다.
화면이 점차 밝아지는 FadeIn, 점차 어두워지는 FadeOut 을 연출해보겠다.
이 연출은 화면을 전부 덮는 이미지를 만들어두고 이미지의 투명값을 조절하여 만들 수 있다.
1. 화면을 덮을 이미지 생성
결과
실제 플레이되는 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번 낮추는데 이 연산 속도가 매우 빨라서 우리 눈에는 찰나의 순간으로 보여
플레이 하자마자 바로 투명한 이미지가 보이는 것이다.
그럼 우리는 어떻게 해야할까?
바로 연산 진행 사이에 대기시간을 추가하는 것이다.
일반적인 코드 진행은 순차적으로 + 쉬지 않고 진행된다.
코루틴은, 코드 사이에 대기 시간을 넣어 코드의 진행에 딜레이를 줄 수 있다.
'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 함수 호출을 통해 코루틴의 동작을 중단할 수 있다.
모든 코드들은 위에서 아래로 순차적으로 진행되고, 이전 코드가 끝나지 않으면 다음 코드가 실행되지 않는다.
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의 시간이 걸릴 것 같다.
실행 결과
시작과 동시에 Function1 과 Function2가 실행되고, "모든 함수 종료" 라는 Start() 함수의 디버그 로그가 출력된다.
그 후 3f의 시간 후 Function1 이 종료되고, 동시에 5f의 시간 후 Function2 가 종료된다.
이러한 현상을 우리는 "비동기방식(ASyne)" 이라고 말한다.
A가 시작되고 이후에 B가 시작되는데 이 때, A와 B가 공통적으로 진행되는 순간이 존재한다.
C의 경우도 마찬가지다.
이처럼 코드가 공통적으로 진행되는 순간,
코드를 병렬적으로 처리할 수 있게 하는 함수가 바로 코루틴 함수이다.
이 사진처럼 한 시점에 여러 작업이 동시에 처리되는 구간이 존재하고, 이러한 처리 방식을 이용해서 우리는
멀티 스레드 프로그래밍이 가능해진다.
코루틴과 반대되는 개념으로 '동기방식(Syne)'이 있다.
순차적이고, 직렬적인 방식이라고 볼 수 있다.
+ 코루틴의 활용 : 반복문
만약 일반 함수를 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 |