=================================
=================================
=================================
이 글은 유니티의 코루틴이 정확히 무엇인지, 내부적으로 어떻게 작동하는지, 그리고 코루틴을 좀 더 최적화 할 수 있는지 알아보려고 작성한다.
Coroutine은 진입점이 여러개인 함수를 의미한다. 일반적인 메서드는 한 번 실행이 시작되면 실행이 종료될 때까지 메서드 호출자에게 실행 제어를 넘기질 않는다. 쉽게 말하면 A메서드에서 B메서드를 호출하면 B메서드의 실행이 종료될 때까지 A메서드는 가만히 기다리고 있어야 한다는 것이다. 그러나 코루틴은 메서드를 실행하는 중간에 메서드 호출자로 진입하는 것이 가능하다.
유니티는 수 많은 사람들의 의문에도 불구하고 Thread-Safety를 전혀 지원하지 않는다. 그래서 비동기에 가까운 작업을 하기 위해서 코루틴을 애용하는 사람들이 많다.
코루틴은 생각보다 이해하기 쉬우며, 정말 강력한 기능을 제공해준다.
void Start() { StartCoroutine(SomeCoroutine()); } IEnumerator SomeCoroutine() { Debug.Log("Start Coroutine"); yield return new WaitForSeconds(1f); Debug.Log("Waited!"); yield return null; Debug.Log("End Coroutine!"); }
우선 위와 같은 코루틴이 있다고 쳐보자.
이 코루틴은 다음과 같은 순서로 동작하게 될 것이다.
1. Start에서 SomeCoroutine이라는 코루틴을 시작하고, 즉시 "Start Coroutine" 이라는 디버그 메세지를 출력한다.
2. 1초를 대기한 다음, "Waited!"라는 디버그 메세지를 출력한다.
3. 1프레임을 대기한 다음 "End Coroutine"라는 디버그 메세지를 출력한다.
4. 코루틴 종료.
와우! 뭔가 비동기 작업을 손쉽게 할 수 있네요! 근데 이런 킹왕짱 코루틴은 어떻게 작동하는 걸까?
코루틴이 어떻게 작동하는지 이해하기 위해선 우선 yield 구문부터 이해해야 한다.
yield라는 것은 반복자의 IEnumerator 객체에 값을 전달(yield)하거나, 반복의 종료를 알리기 위해 사용한다.
유니티 코루틴에서는 다음과 같이 사용한다.
yield statement: yield return object; yield break;
여기서 yield 구문에는 몇 가지의 제약 사항이 존재한다.
1. 메서드 밖에서 yield를 쓰면 에러.
2. 익명 메서드 혹은 람다에서 yield를 쓰면 에러.
3. try-catch-finally에서 yield를 쓰면 대부분 에러.
그렇다... Exception 체크를 하면서 yield 구문을 사용하는 것은 불가능하다...
그렇다면 코루틴에서 yield 구문은 어떻게 작동하는 걸까?
1. yield return
yield return에는 object 타입의 값을 전달하는 역할을 한다.
메서드의 실행 도중에 yield return object에 도달하면 작동하는 순서는 아래와 같다.
1. IEnumerator 객체의 Current 값에 해당 object를 대입한다.
2. 코루틴 메서드의 실행이 일시 정지된다.
3. 엔진에서 Current에 있는 object 값을 가져온다.
4. object의 타입을 체크한 다음, 상황을 판단한다. 만약 object가 WaitForSeconds라면 엔진에서 해당 seconds까지 기다린다.
5. 호출자(유니티 엔진)가 다음 루틴을 실행해도 좋다고 판단했을 경우 MoveNext를 통해 다음 yield 구문을 향해 넘어간다. 만약 다음 yield 구문이 존재하지 않으면 코루틴을 종료한다.
엔진에서 MoveNext 메서드를 호출하면 흐름은 다시 코루틴 내부로 넘어가게 되고, 일시 정지됐던 루틴을 다시 실행하는 것이다.
2. yield break
yield break는 코루틴의 종료를 의미한다. 실행 제어를 코루틴에서 엔진(호출자)에게 바로 넘겨준다. 때문에 yield break 이후에 존재하는 루틴에는 접근할 수 없다.
(아직 작성중, 글 쓰고 보니까 ppt로 만드는게 이해시키기엔 더 쉽겠다...)
다음 글에선 StartCoroutine에 대해 살펴보도록 하겠다.
=================================
=================================
=================================
출처: https://funfunhanblog.tistory.com/32
코루틴 Coroutine
유니티 Update( )함수는 게임의 지속적인 변화를 주거나 게임의 진행되는 매순간 체크(사용자의 입력 등)해야할 경우 사용하게 된다.
하지만 특정행동을 5초 동안 취해야 할 경우, 초당60~80(프레임)번 호출 되는 Update함수 안에서는 제어 하기가 힘들다.
그리고 플레이하는 디바이스마다 각각 다른 프레임이 나오기 때문에 구현 자체가 더더욱 힘들다.
그래서 C#과 유니티에서는 코루틴이라는 것을 제공한다.
유니티에서 사용할 것이기 때문에 유니티 코루틴을 알아보도록 하자
사용법
StartCoroutine
void 함수명( ) //Update안에 있는
{
StartCoroutine( 코루틴 함수 이름( ) );
}
IEnumerator public IEnumerator 코루틴 함수 이름( ) //코루틴 사용
{
Debug.log(코루틴 대기);
yield return new WaitForFixedUpdate();
Debug.log(코루틴 완료);
}
코드분석
우선 StartCoroutine( ) 괄호안에 코루틴으로 IEnumerator 개채명, 지정한 함수이름을 써준다.
yield라는 것은 반복자의 IEnumerator객체에 값을 전달하거나, 반복의 종료를 알리기 위해 사용한다.
WaitForFixedUpdate( ); 다음 FixedUpdate 물리 프레임 전까지 대기
(코루틴 예외 : 함수안에서 만 사용, 알수 없는 이름의 함수(람다)에서는 에러)
코루틴용 데이터 | 엔진이 수행하는 기능 |
yield return null | 다음 프레임까지 대기 |
yield return new WaitForSeconds(float) | 지정된 초 만큼 대기 |
yield return new WaitForFixedUpdate() | 다음 물리 프레임까지 대기 |
yield return new WaitForEndOfFrame() | 모든 렌더링작업이 끝날 때까지 대기 |
yield return StartCoRoutine(string) | 다른 코루틴이 끝날 때까지 대기 |
yield return new WWW(string) | 웹 통신 작업이 끝날 때까지 대기 |
yield return new AsyncOperation | 비동기 작업이 끝날 때까지 대기 |
참고 : https://docs.unity3d.com/kr/530/Manual/Coroutines.html
=================================
=================================
=================================
출처: https://funfunhanblog.tistory.com/90
코루틴Coroutine 작동원리
코루틴?
코루틴은 실행을 중지하여 Unity에 제어권을 돌려주고, 그러나 계속할 때 는 다음 프레임에서 중지한 곳부터 실행을 계속할 수 있는 기능이다. 함수를 호출하면 반환값을 반환하기 전에 실행 완료됩니다. 즉 , 함수에서 수행되는 작업은 하나의 프레임에서 수행된 다는 것을 의미하고, 함수 호출은 절차적 애니메이션을 포함하거나 시간의 경과 함께 일련의 이벤트에는 사용할 수 없다.
<유니티 공식 메뉴얼>
유니티로 게임 제작을 하다보면 코루틴을 많이 사용하게 된다. 쓰레드의 대해서 정확하게 알지는 못하지만 유니티는 단일 쓰레드로 동작한 다는것은 알고 있었다. 그렇다면 유니티에서 멀티쓰레드처럼 멀티태스킹이 불가능한걸까? 코루틴이 바로 멀티 쓰레드처럼 비슷하게 작동하게 해주는 것이 코루틴이다. 그렇다고 멀티쓰레드가 되는것은 아님
코루틴은 어떻게 작동될까?
코루틴은 IEnumerator를 반환한다. C#은 이터레이터 인터페이스는 프로그래머가 IEnumeraotr를 구현 할 수 있도록 도와준다.
진입하는 지점을 한 개인 보통 서브루틴 방식과 다르게 진입하는 지점까지 여러 개를 가질 수가 있다. yield return을 통해 그 바로전 시점을 기억하고 다음 호출하게 될떄 그 다음부터 실행이 되는 것이다.
유니티에서는 대부분 그 시점을 Update에서 체크한다.
코루틴을 사용할 때 IEnumerator와 같이 사용한다. 이 IEnumerator는 데이터의 목록을 하나씩 넘겨줄 때 사용되는 인터페이스인데, 코루틴은 호출 한 함수와 상호작용하면서 진행되는데 자신을 호출한 함수에 데이터를 하나 넘겨주고 쉬게되는데, 받은 함수에서는 데이터를 받고 처리한 후에 코루틴에게 다음 데이터를 달라고 요청하게 된다.
(서브 루틴 : 일반적인 함수에서 사용되는 작동개념인데 함수는 시작할 때 진입하는 지점이 저장하고, return구문에 의해서 종료되는 지점을 저장한다.
Iterator :컬렉션에 대해 사용자 지정 반복을 수행, yield return 문을 사용하고 각 요소를 한 번에 하나씩 반환한다. 이터레이터는 현재 위치를 기억하고 다음 반복에서는 다음 요소를 반환.)
학습 참고:
2). https://seungngil.tistory.com/
=================================
=================================
=================================
*기타관련링크
- https://prosto.tistory.com/68
- http://blog.naver.com/PostView.nhn?blogId=pxkey&logNo=221296053953&categoryNo=64&parentCategoryNo=0
- https://linecode.tistory.com/9
- https://unityindepth.tistory.com/21
- https://iflife1124.tistory.com/18
- https://kimseunghyun76.tistory.com/304
=================================
=================================
=================================
'게임엔진관련 > 유니티 엔진' 카테고리의 다른 글
[Unity] 유니티 마스크 관련 (0) | 2019.07.30 |
---|---|
[Unity] 유니티 해상도, 화면크기와 오브젝트, 3D위치 고정 매핑 관련 (0) | 2019.07.24 |
[Unity] 유니티, 해제 이벤트 함수 3형제: OnApplicationQuit, OnDisable, OnDestroy 관련 (0) | 2019.07.21 |
[Unity] 유니티 가격정책 관련 (0) | 2019.07.12 |
[Unity] 유니티 스플래시 화면 관련 (0) | 2019.07.12 |