스크립트에서 특정 코드를 읽는 동안에는 다른 코드는 실행하지 못한다. 이 말은 내가 A 함수를 읽고 있는 동시에 B 함수까지 읽어내려갈 순
없다는 것이다. A함수에서 코드를 읽어 내려가다가 특정 부분에서 '2초간 멈추어라' 라는 명령이 있다면 가만히 2초를 기다릴 뿐이지,
B함수에 들렀다가 2초 후에 다시 A함수로 돌아오는 등의 일은 일어나지 않는다. 만약 위의 예시에서 2초를 기다리는 동안 다른 코드들을
읽고 다시 돌아와 기다린 시점부터 다시 코드를 실행시키고 싶다면 코루틴을 이용하면 된다.
* Coroutine
코루틴은 IEnumerator을 반환형으로 갖는다.
ex ) IEnumerator test() { }
위의 코루틴을 실행시키려면 단순히 test() 로 실행시키는 것이 아니라, StartCoroutine( test() ); 와 같이 실행시켜주어야 한다.
코루틴의 { } 안에 반환형을 충족시켜주기 위해서는 yield가 들어간다.
ex) IEnumerator test() { yield return ...; }
yield는 '양보하다'라는 뜻 처럼 사용자가 지정한 만큼 다른 곳에 코드를 읽다가 돌아온다. 아래의 예시를 보면 확실하게 알 수 있다.
public class test : MonoBehaviour { // Start is called before the first frame update void Start() { StartCoroutine(CoroutineTest()); Debug.Log("Start"); } IEnumerator CoroutineTest() { yield return new WaitForSeconds(1f); Debug.Log("Coroutine"); } }
위의 Start() 안의 코드를 보면 ,먼저 CoroutineTest() 를 실행한 뒤에 콘솔에 Start를 출력해주도록 하고 있다.
따라서 코드의 순서상으로는 CoroutineTest에서 WaitForSeconds(1f), 즉 1초를 쉰 뒤에 콘솔에 "Coroutine"을 실행하고 그 다음 Start() 로 돌아가
콘솔에 "Start"를 실행할 것으로 보인다.
하지만 위의 결과는 "Start"가 먼저 출력된 후에 "Coroutine"이 출력된다. 이 말은 yield return new WaitForSeconds(1f); 부분에서 1초 동안
기다리는 동안 Debug.Log("Start") 를 실행하고 온 것이다.
null 1 프레임
new WaitForSeconds(x) x초 기다려라
StartCoroutine 코루틴이 끝날 때 까지 기다려라
WWW 웹 정보를 받아올 때까지 기다려라
* null의 경우 1프레임을 기다리는 것은 매 프레임마다 실행되는 Update() 와 비슷해 보인다.
그러나 Update() 의 경우 매 프레임마다 계속 실행되는 반면에 코루틴은 한번 실행되고 나면 다시 호출하기 전까지 실행되지 않는다.
즉 Coroutine으로 구현 가능한 부분을 Update()에 두게 되면 끝난 후에도 무의미한 조건검사를 계속할 것이고 이는 게임 성능을 저하시킨다.
이처럼 Update() 의 부분을 최대한 Coroutine으로 빼서 구현하는 것이 게임 최적화를 하는 것으로 볼 수 있다.
* StartCoroutine의 경우 한 코루틴에서 여러 코루틴을 사용할 때 유용하다.
만약에 A 코루틴 내에 B와 C 코루틴을 실행한다고 생각해보자.
IEnumerator A() { StartCoroutine(B()); yield return new WaitForSeconds(1f); StartCoroutine(C()); } IEnumerator B() { yield return new WaitForSeconds(2f); Debug.Log("B"); } IEnumerator C() { yield return new WaitForSeconds(2f); Debug.Log("C"); }
만약 내가 원한 실행의 순서가 B 코루틴이 실행된 후 1초 기다렸다가 C 코루틴이 실행되는 것이라면, 위와 같은 코드는 생각대로 실행되지 않는다.
B 코루틴에서 2초 기다리면서, B가 끝나기도 전에 A 코루틴의 WaitForSeconds(1f)가 실행되고 바로 C가 실행되기 때문이다.
우리가 본래 원했던, B가 실행된 후에 A코루틴이 마저 실행되기를 원한다면 A 코루틴을 아래와 같이 바꾸어주면 된다.
IEnumerator A() { yield return StartCoroutine(B()); yield return new WaitForSeconds(1f); yield return StartCoroutine(C()); }
'Unity 공부시작' 카테고리의 다른 글
유니티 :: 충돌 지점 알아내기(2D) (0) | 2019.01.13 |
---|---|
유니티 :: 화면 부드럽게 움직이기 [ SmoothDamp() ] // SmoothFollow (0) | 2019.01.13 |
유니티 :: 오브젝트 풀링 (0) | 2019.01.12 |
유니티 :: Dictionary에 TextAsset을 이용하여 텍스트 파일 읽어오기 (0) | 2019.01.11 |
유니티 :: 컬렉션 ( List, Stack, Dictionary ) (0) | 2019.01.11 |