[목차]
#0 코루틴(Coroutine)을 사용하는 이유
#1 코루틴 사용 예제
#1.1 코루틴 선언 IEnumerator
#1.2 코루틴 실행 StartCoroutine()
#2 코루틴 중지
#3 yield return VS yield break
* 다음 포스팅은 개인적인 공부 내용을 기록한 글이기에, 잘못된 내용이 있을 수 있으며 지속적으로 수정해 나갈 예정입니다.
#0 코루틴(Coroutine)을 사용하는 이유
유니티에서 Update() 메소드는 화면에 변화를 일으킬 때 사용 하고는 합니다. Update() 메서드는 매 프레임마다 호출이 되기에, 60fps라면 1초에 60번이 호출 됩니다. 그런데 만약 5초동안 지연을 시켜야 하는 상황이 발생 한다면 어떻게 될까요?
Update() 메서드를 5 * 60 = 300번 호출하면 될 것입니다. 하지만 이러한 딜레이가 발생하는 상황을 모두 Update() 구문에 정의하면 기기의 성능에 따라서 프레임 드랍(Frame Drop) 을 발생하고 맙니다. 이 때 코루틴(Coroutine)을 사용하면, Update() 함수를 굳이 300번이나 호출하지 않고도 시간을 지연 시키는 것이 가능합니다.
#1 코루틴 사용 예제
코루틴을 사용하지 않은 예제와, 코루틴을 사용한 예제 두 가지 소스코드로 나누어 비교해 보도록 하겠습니다.
RPG게임에서 포션을 마시고 다음 포션을 마실 때 까지의 딜레이를 5초를 설정하여 포션을 연속으로 마시지 못하게 하는 상황을 예시로 들겠습니다.
우선, 빈 오브젝트(Character)와 C#스크립트(PotionDelay) 를 하나 씩 생성해 준 뒤 스크립트를 부착해 줍니다.
아래는 코루틴을 사용하지 않은 PotionDelay 예제 입니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PotionDelay : MonoBehaviour
{
public bool isDelay;
public float delayTime = 5.0f;
public float accumTime;
void Update()
{
if(Input.GetKeyDown(KeyCode.Space))
{
if(isDelay == false)
{
isDelay = true;
Debug.Log("HP가 50 회복 되었습니다.");
}
else
{
Debug.Log("아직 포션을 사용할 수 없습니다.");
}
}
if(isDelay)
{
accumTime += Time.deltaTime;
if(accumTime >= delayTime)
{
accumTime = 0.0f;
isDelay = false;
}
}
}
}
Space 를 누르면 isDelay 변수가 false인 경우 "HP가 50 회복 되었습니다." 라는 문구를 출력하고, isDelay 변수가 true인 경우 "아직 포션을 사용할 수 없습니다." 라는 문구를 출력합니다.
그렇게 어려운 코드는 아니기에 설명은 생략 하도록 하겠습니다. 이제 이 코드를 코루틴을 사용해 수정해 보도록 하겠습니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PotionDelay : MonoBehaviour
{
public bool isDelay;
public float delayTime = 5.0f;
public float accumTime;
void Update()
{
if(Input.GetKeyDown(KeyCode.Space))
{
if(isDelay == false)
{
isDelay = true;
Debug.Log("HP가 50 회복 되었습니다.");
StartCoroutine(Drink());
}
else
{
Debug.Log("아직 포션을 사용할 수 없습니다.");
}
}
}
IEnumerator Drink()
{
yield return new WaitForSeconds(5.0f);
isDelay = false;
}
}
실행 결과는 동일합니다. 이제, 코루틴 사용방법을 설명 하도록 하겠습니다.
#1.1 코루틴 선언 IEnumerator
코루틴의 선언은 반환형을 IEnumerator 로 설정 합니다. 그리고 일반적인 함수와 달리 반환 시 return 이 아닌, yield return 으로 돌려 주어야 합니다.
yield return 뒤에는 반환 시간을 명시해 주는데, 명시한 반환 시간 만큼 유니티에 제어권을 돌려주어 코드 동작을 중지시키고, 시간이 지나면 다음 줄 부터 다시 코루틴이 동작합니다. 대표적인 반환 시간의 타입은 다음과 같습니다.
[1] null : 1frame 만큼 코드 동작을 중지 시킵니다.
[2] new WaitForSeconds(s) : s초 만큼 동작을 중지 시킵니다.
(* 다른 반환 타입의 종류가 궁금하시다면, 유니티 공식 사이트의 메뉴얼을 참고해 주세요)
#1.2 코루틴 실행 StartCoroutine()
코루틴의 실행 방법은 일반 함수와는 달리, StartCoroutine() 메소드를 이용하여 괄호 안에 코루틴이름() 을 넣어 주어야 합니다.
혹은 아래와 같이 "코루틴 이름" 으로도 실행이 가능합니다.
StartCoroutine("Drink");
#2 코루틴 중지
다음으로, 코루틴을 중지 시키는 방법에 대해서 정리 하도록 하겠습니다. 아래는 코루틴이 1초마다 로그를 출력하고, space 키를 누르면 코루틴을 중지하는 예제입니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CourutineTest : MonoBehaviour
{
void Start()
{
StartCoroutine("Test");
}
void Update()
{
if(Input.GetKeyDown(KeyCode.Space))
{
StopCoroutine("Test");
Debug.Log("STOP CORUTINE");
}
}
IEnumerator Test()
{
int i = 1;
while (true)
{
yield return new WaitForSeconds(1.0f);
Debug.Log(i + "초");
i++;
}
}
}
코루틴은 StopCoroutine() / StopAllCoroutines() 함수로 중지 시킬 수 있습니다.
StopCoroutine() 함수는 해당하는 코루틴만 중지시키고, StopAllCoroutines() 함수는 모든 코루틴을 중지시킵니다.
#3 yield return VS yield break
마지막으로 yield return 과 yield break 의 차이에 대해서 설명하고 마치도록 하겠습니다.
#1에서 yield return은 지정한 시간만큼 유니티에 제어권을 넘겨주어 대기하는 키워드라고 설명했습니다. yield return과 달리 yield break 문은 해당 키워드를 만나자 마자 코루틴을 빠져나옵니다. 아래 코드를 실행시켜 보면,
public class CourutineTest : MonoBehaviour
{
void Start()
{
StartCoroutine(Return());
StartCoroutine(Break());
}
IEnumerator Return()
{
Debug.Log("Return() 1");
yield return null;
Debug.Log("Return() 2");
}
IEnumerator Break()
{
Debug.Log("Break() 1");
yield break;
Debug.Log("Break() 2");
}
}
yield break; 아래의 Debug.Log("Break() 2")는 출력되지 않고 , 코루틴이 끝나 버렸음을 확인 가능합니다.
'Archive > GameDevelop' 카테고리의 다른 글
[Unity2D] Unit(유닛) & Pixels Per Unit (0) | 2021.06.19 |
---|---|
[Unity] Raycast _ 레이캐스트 총 정리 (1) | 2021.06.18 |
[Unity Error] 'System.Collections.IEnumerable' 에서 'string'(으)로 변환 할 수 없습니다. 해결방법 (0) | 2021.06.16 |
[Unity] Time.deltaTime (0) | 2021.06.15 |
[Unity Function] 충돌 처리 Collision & Trigger 관련 함수/예제 (0) | 2021.06.13 |