기본적인 사용법은 IEnumerator로 함수를 구현하고, StartCoroutine으로 해당 함수를 코루틴으로 실행시키는 것이다.
필요한 곳에 yield return을 해주어 분기점을 설정하자.
IEnumerator을 사용하므로 using System.Collections;를 잊지 말도록 하자.
활용법 Ⅰ
시간이 지남에 따라 점진적으로 결과를 보여주고자 할 때의 활용법이다.
검은색 이미지를 화면에 채운 뒤 FadeCoroutine 스크립트를 부착시켰다.
FadeCoroutine 스크립트는 다음과 같다. (유니티 공식 문서 코드 참고)
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
publicclassFadeCoroutine : MonoBehaviour
{
public Image image;
voidStart()
{
StartCoroutine(Fade());
}
IEnumerator Fade()
{
for (float f = 1f; f >= 0; f -= 0.1f)
{
Color c = image.color;
c.a = f;
image.color = c;
yieldreturnnewWaitForSeconds(0.1f);
}
}
}
yield return new WaitForSeconds를 활용해 0.1초마다 이미지의 알파(투명도)값을 0.1씩 낮춘다.
코루틴이 일시 정지 되는 동안 루프 카운트, 멤버변수, 매개변수가 모두 보존된다.
실행 화면은 다음과 같다.
Fade 함수가 코루틴이 아닌 일반 함수였다면,
for문이 모두 끝난 후 알파값이 적용되어 정상적으로 Fade in 되지 않고 즉시 이미지가 투명해지는 상황이 벌어질 것이다.
활용법 Ⅱ
어느 시점으로부터 일정 시간 이후 작업을 진행하고자 할 때의 활용법이다.
버튼에 Coroutines 스크립트를 부착 후,
On Click 이벤트에 해당 버튼의 Coroutines 스크립트의 PressButton 함수를 연결해주었다.
Coroutines 스크립트는 다음과 같다.
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
publicclassCoroutines : MonoBehaviour
{
constfloat delayTime = 2f;
publicvoidPressButton()
{
StartCoroutine(ChangeColor());
}
IEnumerator ChangeColor()
{
yieldreturnnewWaitForSeconds(delayTime);
Color c = GetComponent<Image>().color;
c.b = 0f;
GetComponent<Image>().color = c;
}
}
delayTime 이후에 그 아래의 작업들이 진행될 것이다.
실행 화면은 다음과 같다.
활용법 Ⅲ
프레임마다 호출이 아닌, 일정 시간마다 호출하여 연산의 수를 줄이고자 할 때의 활용법이다.
다음과 같이 작성 시, Update 함수에서 프레임마다 호출하는 것보다 프레임 드랍을 줄일 수 있다.
using System.Collections;
using UnityEngine;
publicclassMyCoroutine : MonoBehaviour
{
public Transform player;
public Transform enemy;
voidStart()
{
StartCoroutine(CountNumber());
}
IEnumerator CountNumber()
{
while (true)
{
if (Vector3.Distance(player.position, enemy.position) < 10f)
Debug.Log("Detected Player");
yieldreturnnewWaitForSeconds(0.2f);
}
}
}
활용법 Ⅳ
하나의 Coroutine객체로 코루틴을 관리하는 활용법이다.
다음은 버튼을 눌러 코루틴을 시작하고, 키보드의 Space 키를 눌러 해당 코루틴을 종료하는 스크립트이다.
기본적으로 StopCoroutine(IEnumerator enumerator)으로 enumerator가 실행되고있는 코루틴을 종료할 수 있고,
StopAllCoroutines()로 해당 스크립트의 진행되고 있는 모든 코루틴을 종료할 수 있다.
using System.Collections;
using UnityEngine;
publicclassCoroutines : MonoBehaviour
{
constfloat delayTime = 2f;
Coroutine state;
publicvoidPressButton()
{
if (state == null)
state = StartCoroutine(StartDelay());
}
privatevoidUpdate()
{
if (Input.GetKeyDown(KeyCode.Space))
{
if (state != null)
{
StopCoroutine(state);
Debug.Log("Stopped Coroutine");
state = null;
}
}
}
IEnumerator StartDelay()
{
Debug.Log("Start");
yieldreturnnewWaitForSeconds(delayTime);
Debug.Log("End");
state = null;
}
}
동일한 코루틴을 연속해서 StartCoroutine하면 여러개의 동일한 코루틴이 실행되므로 주의하자.
이는 원래의 목적과는 다르게 진행될 것이며, StopCoroutine 또한 처음 시작된 하나의 코루틴만 종료시키게 된다.
하지만, Coroutine객체를 활용하여 위의 스크립트처럼 관리한다면 안정적으로 코루틴을 관리할 수 있다.
이를 응용하면 여러개의 코루틴을 순환하며 관리할 수도 있다.
실험을 통한 이해
코루틴의 동시성을 이해하기 위한 코루틴의 진행 순서 실험
using System.Collections;
using UnityEngine;
publicclassMyCoroutine : MonoBehaviour
{
int updateCnt = 1;
int lateUpdateCnt = 1;
voidStart()
{
Debug.Log("Start");
StartCoroutine(CountNumber());
}
voidUpdate()
{
if (updateCnt < 4)
Debug.Log("Update " + updateCnt++);
}
voidLateUpdate()
{
if (lateUpdateCnt < 4)
Debug.Log("LateUpdate " + lateUpdateCnt++);
}
IEnumerator CountNumber()
{
Debug.Log("Coroutine 1");
yieldreturnnull;
Debug.Log("Coroutine 2");
yieldreturnnull;
Debug.Log("Coroutine 3");
}
}
Start 함수에서 StartCoroutine한 후, Update와 LateUpdate 실행 순서를 확인한다.
결과는 다음과 같다.
코루틴은 StartCoroutine 이후 바로 호출되며,
코루틴이 시작된 다음 프레임부터 Update - Coroutine - LateUpdate 순서를 가진다.
대략 이정도 느낌의 동시성으로 진행된다는 것을 알 수 있다.
개인 공부용 포스팅인 점을 참고하시고, 잘못된 부분이 있다면 댓글로 남겨주시면 감사드리겠습니다.