목표
- Coroutines에 대해 알아보자.
Unity Thread 구조
- Unity는 기본적으로 싱글스레드 기반으로 동작했다.
- 2019년에서야 DOTS(Data-Oriented Technology Stack)등장했고, 멀티스레드 환경을 지원했다.
- 복잡하지 않은 게임을 만들거나, 스크립트를 막 공부한 사람이라면 싱글스레드 환경에서 개발하게 될 것이다.
코루틴(Coroutine)
- Update 함수를 통해 프로그램 내용을 갱신할 수 있다.
- 다만 Update 함수에서 작업이 완료되지 않으면, 다음 frame으로 넘어가지 않고 작업 완료를 대기한다.
- 함수의 작업시간이 길다면 frame이 넘어가지 않아 렉이 발생한다.
- 이 문제를 해결하기 위해 Unity는 시분할(time-sharing) 방식의 Coroutine 사용한다.
예제
- 코루틴은 StartCoroutine을 사용하여 호출 할 수 있다.
- 함수는 한번 실행 되지만, 리턴되는 결과는 1, 2, 3 이다.
- yield return 문을 만나기까지 동작하고, 중간 중간 결과를 리턴한다.
- 마지막 yield return이 실행되면, 종료된다.
void Start()
{
StartCoroutine(Numbers());
// 혹은 아래와 같은 방식으로 호출 가능하다.
// StartCoroutine("Numbers");
}
IEnumerator Numbers()
{
yield return 1;
yield return 2;
yield return 3;
}
- Unity에서는 알파 채널값(투명도) 감소를 예제로 제시하고 있다.
- 코루틴을 사용하지 않고, Fade 함수를 호출하면 알파가 감소되는 과정을 볼 수 없다.
void Start()
{
// 여기서는 알파가 1인 상태
Fade();
// 여기서는 알파가 0인 상태
}
void Fade()
{
// 알파값을 1부터 0까지 줄임
// 알파가 0이면 투명해짐
for (float f = 1f; f >= 0; f -= 0.1f)
{
// 색깔
Color c = renderer.material.color;
// 감소된 알파값 적용
c.a = f;
renderer.material.color = c;
}
}
- 하지만 코루틴을 사용하면, 알파의 변화 과정을 볼 수 있다.
// StartCoroutine은 MonoBehaviour를 상속 받은 클래스에서만 동작한다.
public class SampleScript : MonoBehaviour
{
void Start()
{
// 코루틴 함수는 StartCoroutine 함수로 호출한다.
StartCoroutine("Fade");
}
// 코루틴 함수는 IEnumerator 리턴형을 가진다.
IEnumerator Fade()
{
for (float f = 1f; f >= 0; f -= 0.1f)
{
Color c = renderer.material.color;
c.a = f;
renderer.material.color = c;
// yield return은 여기까지 실행되고 frame을 넘기라는 뜻
yield return null;
}
}
}
- 여기서 문제가 발생한다. 보통 60fps이면 1frame에 0.01666초라는 소리인데... 이걸 본다고?
- 이 문제를 해결하기 위해, WaitForSeconds를 사용한다.
// StartCoroutine은 MonoBehaviour를 상속 받은 클래스에서만 동작한다.
public class SampleScript : MonoBehaviour
{
void Start()
{
// 코루틴 함수는 StartCoroutine 함수로 호출한다.
StartCoroutine("Fade");
}
// 코루틴 함수는 IEnumerator을 리턴형으로 가진다.
IEnumerator Fade()
{
for (float f = 1f; f >= 0; f -= 0.1f)
{
Color c = renderer.material.color;
c.a = f;
renderer.material.color = c;
// WaitForSeconds를 사용하면, 다음 코루틴의 실행까지 대기 시간을 설정할 수 있다.
yield return new WaitForSeconds(1f);
}
}
}
반환형 | 설명 |
yield return null | 다음 프레임까지 대기 |
yield return new WiatForSeconds(float) | 지정된 시간(초)만큼 대기 |
yield return new WaitForFixedUpdate() | 다음 물리 업데이트 프레임까지 대기 |
yield return new WaitForEndOfFrame() | 현재 프레임이 끝날때까지 대기 |
yield return StartcoRoutine(string) | 새로운 코루틴 함수를 실행하고, 그 함수가 종료될때까지 대기 |
yield return new WWW(string) | 통신 작업이 끝날 때까지 대기 |
yield return new AsyncOperation | 비동기 작업이 완료되기 전까지 대기 |
코루틴 중지
- StopCoroutine을 사용하면 코루틴을 중지하는 방법은 3가지가 있다.
public class SampleScript : MonoBehaviour
{
private IEnumerator enumerator;
private Coroutine coroutine;
void Start()
{
enumerator = Fade();
// 코루틴 함수는 StartCoroutine 함수로 호출한다.
coroutine = StartCoroutine(enumerator);
}
void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
// IEnumerator로 실행할 코루틴을 저장하고 있다가 정지에 사용하는 방법
StopCoroutine(enumerator);
}
if (Input.GetKeyDown(KeyCode.B))
{
// 함수 이름으로 현재 동작중인 코루틴을 찾아 중지하는 방법
StopCoroutine("Fade");
}
if (Input.GetKeyDown(KeyCode.C))
{
//코루틴으로직접 중지하는 방법
StopCoroutine(coroutine);
}
}
IEnumerator Fade()
{
for (float f = 1f; f >= 0; f -= 0.1f)
{
Color c = renderer.material.color;
c.a = f;
renderer.material.color = c;
yield return new WaitForSeconds(1f);
}
}
}
- 혹은 yield break를 사용하여 코루틴을 즉시 정지시킬 수 있다.
IEnumerator Fade()
{
for (float f = 1f; f >= 0; f -= 0.1f)
{
Color c = renderer.material.color;
c.a = f;
if (f <= 0.4f)
{
// 코루틴 즉시 정지
yield break;
}
renderer.material.color = c;
yield return new WaitForSeconds(1f);
}
}
'프로그래밍 > Unity C#' 카테고리의 다른 글
[Unity] Tutorial 06 - Intermediate Scripting (Delegates) (0) | 2020.05.27 |
---|---|
[Unity] Tutorial 06 - Intermediate Scripting (Quaternions) (0) | 2020.05.27 |
[Unity] Tutorial 06 - Intermediate Scripting (Collections) (0) | 2020.05.27 |
[Unity] Tutorial 06 - Intermediate Scripting (Nampespace) (0) | 2020.05.27 |
[Unity] Tutorial 06 - Intermediate Scripting (Extension Methods) (0) | 2020.05.27 |