💛 C#에서 일반적인 메서드는 단일 프레임 내에서 실행된다.
행된다.
Monobehaviour을 상속받아야 한다.IEnumerator를 반환해야 한다.yield return (조건)을 사용해야 한다.IEnumerator 함수이름()
{
yield return (조건);
}IEnumerator🩵 열거자 (Enumerator)
- 배열, 컬렉션을 단순히 열거 및 순회하기 위해 만들어진 것
(foreach문에서 사용된다.)- 한 프레임 내에 실행된다.
- 코루틴은 열거자를 기반으로 만들어졌지만, 열거할 때마다 원하는 특정 프레임에 실행되도록 작동한다.
yield return
해당 지점에 도착할 경우, 코루틴은 코드의 동작을 중지하고 대기한다.
= 코드의 제어권을 유니티에 다시 돌려준다.
= 실행되는 프레임이 달라진다.
대기 조건이 충족되면 다시 코루틴이 다음 줄부터 실행된다.
종류
// null : 다음 Update 호출까지 기다림 (한 프레임 동안 대기)
yield return null;
// WaitForSeconds: 매개변수(초, 유니티 시간) 동안 기다림
yield return new WaitForSeconds(1f);
// WaitForSecondsRealtime : 매개변수(초, 실제 시간) 동안 기다림
yield return new WaitForSecondsRealtime(1f);
// WaitForFixedUpdate : 다음 Fixed Update 호출까지 기다림
yield return new WaitForFixedUpdate();
// WaitForEndOfFrame : 모든 렌더링 작업이 완료될 때까지 기다림
yield return new WaitForEndOfFrame();
// WaitUntil : 조건이 참이 될 때까지 기다림
yield return new WaitUntil(() => (조건));
🩵 Realtime
: 유니티의 time scale의 영향을 받지 않는 실제 시간
yield break
해당 지점에 도착할 경우, 코루틴이 완전히 멈추고 제어권이 유니티 엔진에게 넘어간다.
사용 예
: 코루틴 내부에서 특정 조건을 만족할 경우 코루틴을 멈추고자 할 때
: StartCoroutine 이용
IEnumerator TestCoroutine(int count)
{
}StartCorountine(TestCorountine(5));StartCorountine("TestCorountine", 5);StopCoroutine 이용
StartCoroutine(TestCoroutine());
StopCoroutine(TestCoroutine()); : 위와 같은 방식으로 코루틴 함수를 실행시키고 중지시키는 경우, 각 TestCoroutine 함수가 반환한 IEnumerator는 별개의 것이기 때문에 코루틴이 정상적으로 중지되지 않는다.IEnumerator enumerator;
eumerator = TestCoroutine(5);
StartCoroutine(enumerator);
StopCorountine(enumerator);StopCoroutine("TestCoroutine")StopAllCoroutine 이용
코루틴 내부에서 무한 루프를 돌릴 때,
반드시 코루틴 내부의 반복문 안에 yield return을 작성해 적절하게 제어권을 양보해줘야 한다.
IEnumerator InfityLoop()
{
yield return null;
while (true)
{
}
}: 코루틴의 while문 내부에서 유니티로 제어권을 돌려주는 부분이 없기 때문에 코루틴이 제어권을 독점하게 된다. 따라서 유니티 에디터가 멈추는 문제가 발생한다.IEnumerator InfityLoop()
{
while (true)
{
yield return null;
}
}코루틴은 스레드가 아니기 때문에 코루틴은 메인 스레드에서 실행된다.
멀티 스레드와 코루틴은 서로 다른 개념이다.
🩵 비동기(Asynchronous)
- 여러 작업이 동시에 실행되거나, 한 작업이 완료되기 전에 다른 작업이 시작되는 것
- 비동기 작업 != 멀티스레드
코루틴 사용시 가비지가 생성되기 때문에 필요한 부분에만 사용하고, 반복적으로 사용되는 로직이라면 업데이트 함수에서 처리하는 것이 좋다.
StartCoroutine 호출) 과정에서 유니티 내부적으로 가비지가 생성됨new로 생성할 때마다 가비지 생성됨Start 메서드 자체를 코루틴처럼 사용할 수 있다.
IEnumerator Start() {
yield return null;
}
물리 법칙 / 입력 / 렌더링과 관련된 메서드들은 코루틴처럼 사용할 수 있다.
IEnumerator OnCollisionEnter() {
yield return null;
}
IEnumerator OnMouseEnter() {
yield return null;
}
public static class Util : Monobehaviour
{
public static readonly WaitForEndOfFrame WaitForEndOfFrame = new WaitForEndOfFrame();
public static readonly WaitForFixedUpdate WaitForFixedUpdate = new WaitForFixedUpdate();
private static readonly Dictionary<float, WaitForSeconds> _WaitForSeconds = new Dictionary<float, WaitForSeconds>();
public static WaitForSeconds WaitForSecond(float seconds)
{
if(_WaitForSeconds.TryGetValue(seconds, out var waitForSeconds))
{
wfs = new WiatForSeconds(seconds);
_WaitForSeconds.Add(seconds, wfs);
}
return wfs;
}
}