내일 과제 제출을 위해 기존 당근을 먹었을 때 체력과 배고픔만 상승했었는데, 이동속도가 5초간 상승하는 기능을 추가하기 위해 코루틴을 사용하게 되었다. 예전 첫주차에 카드를 뒤집을 때 다른 카드가 안뒤집히게 하기 위해 썼던 함수가 코루틴이었는데 지금와서야 제대로 코루틴에 대해 적어보겠다.
1. 코루틴이란?
우선 어디에 코루틴을 사용해야하는지 알아보자
유니티에서 특정 코드가 반복적으로 실행되기 위해서는 Update문에 코드를 작성하면 되는데,
간혹 Update가 아닌 곳에서도 반복적으로 코드가 실행되어야할 필요가 있을 때가 있다.
이럴 때 코루틴을 사용하는 것이 매우 효과적이다.
또한, 업데이트문을 사용하면 원하든 원하지 않든 업데이트문이 매 프레임마다 계속 반복적으로 실행되지만,
코루틴을 사용한다면 자신이 필요한 순간에만 반복하고 필요하지 않을 때에는 전혀 사용하지 않음으로써 자원관리를 매우 효과적으로 할 수 있다.
그 밖에도 당장 실행되는게 아니라 일정 시간동안 멈춰있다가 그 뒤에 동작하게 하거나 특정 조건을 부여해서 코드가 실행되도록 할 수도 있다.
사용법도 간단하면서 다양하게 활용이 가능하기 때문에
코루틴은 실무에서 굉장히 빈번하게 사용되므로 꼭 자세히 알아둘 필요가 있다.
2. 코루틴 사용 방법
우선 크게 두가지 필수 조건이 있다.
이 두가지가 필수 조건이 되겠다.
기본형은 다음과 같다.
IEnumerator 함수이름()
{
yield return // + 조건
// 함수 내용
}
- yield return의 종류
1. yield return null; : 다음 프레임에 실행 됨.
yield return new WaitForSeconds( float ); : 매개변수로 입력한 숫자에 해당하는 초만큼 기다렸다가 실행됨.
yield return new WaitForSecondsRealtime( flaot ); : 매개변수로 입력한 숫자에 해당하는 초만큼 기다렸다가 실행됨.
yield break;
등등
1번과 2번을 제일 많이 사용하게 된다.
2번과 3번이 무슨 차이인지 궁금할 수 있는데,
3번은 현실의 시간을 기준으로 체크하는 것이고, 2번은 유니티상에서의 시간을 기준으로 체크하는 것이다.
유니티에서 시간은 TimeScale을 사용해서 느리게하거나 빠르게 조절할 수 있는데, 이 값의 변화에 영향을 받는 것이 2번이고 무관한 것이 3번이다.
여기서 코루틴 함수를 생성하면 사용해야하는데 사용하려면
StartCoroutine(코루틴메서드이름());
StartCoroutine("코루틴메서드이름");
이런식으로 불러주어야한다.
3. 실제 사용
그래서 이제 내가 사용한 방법을 알아보자.
나는 당근을 먹었을 때 스피드가 5초동안 증가하는 코드를 만들고 싶어서 코루틴을 사용하였다.
IEnumerator SpeedCarrot(float amount)
{
float originalSpeed = moveSpeed;
moveSpeed += amount;
yield return new WaitForSeconds(5.0f);
moveSpeed = originalSpeed;
}
SpeedCarrot이라는 이름의 코루틴메서드를 만들었다 먼저 기본 스피드를 originalSpeed에 저장해두고 매개변수로 받을 amount만큼 moveSpeed에 더해준다.
그리고 5초후에 그효과가 종료되게끔 WaitForSeconds(5.0f)로 코드를 적어서 5초 후에 종료되게 만들고 그 뒤에 먼저 기본 스피드를 저장해두었던 originalSpeed를 불러와서 기존 스피드로 복구되는 코드를 작성하였다.
이제 이 코루틴 메서드를 다른 cs에서 사용하기 위해 새로 UpSpeed()라는 메서드를 만들어서 startCoroutine을 선언해서 코루틴을 사용할 수 있게 만들었다.
public void UpSpeed(float amount)
{
StartCoroutine(SpeedCarrot(amount));
}
그리고 이제 먼저 만들어두었던 인벤토리에서 사용버튼을 누르면 발동하는 메서드에 이 메서드를 넣어주면 스피드가 오르고 5초 후에 원래대로 돌아오는 것을 확인할 수 있다.
public void OnUseButton()
{
if(selectedItem.type == ItemType.Consumable)
{
for(int i = 0; i < selectedItem.consumables.Length; i++)
{
switch (selectedItem.consumables[i].Type)
{
case ConsumableType.Speed:
controller.UpSpeed(selectedItem.consumables[i].value);
break;
}
}
RemoveSelectedItem();
}
}
제대로 작동되는 것을 영상으로 보여주고 싶은데 영상 올리는 법을 몰라서 못올렸다..
우선 잘 작동된다.
4. Invoke보다 뛰어난 장점
일정 시간 만큼 지연시켰다가 코드를 동작하게 한다는 점에서 Invoke와 동일한 기능을 가지고 있지만,
코루틴에만 있는 훌륭한 장점이 있다.
앞서 말했듯이, 코루틴을 통해서 Update문과는 별개로 동작하는 또다른 서브루틴을 만들 수 있기도 하지만,
그것 말고도 매개변수를 넘길 수 있다는 장점이 있다.
코루틴은 앞에 IEnumerator를 작성한다는 것 말고는 일반적인 메소드와 동일하기 때문에 매개변수를 사용할 수 있다.
따라서 굉장히 자유롭게 코루틴을 쓸 수 있다.
문자열로 메소드 이름을 적어서 코루틴을 동작시킬 경우 ,를 찍어서 매개변수를 전달할 수 있다.
다만 이 경우에는 매개변수가 1개까지만 전달할 수 있다.
반면, 일반적인 메소드를 호출하는 것처럼 적어준다면 여러개의 매개변수를 전달 할 수 있다.
따라서 되도록이면 첫번째 방식으로 코루틴을 호출하여 사용하도록 하자.
성능적인 면에서도 첫번째 방법이 더 좋다.
5. 회고
오늘은 코루틴에 대해 알아보았다. 첫주에 다른 팀원분이 코루틴을 사용했을때는 이게 뭐야? 하면서 그냥 보고만 있었지만 배우고 다시 그부분을 보니 새로웠다. 이게 이런식으로 사용되는거구나! 하면서 다시 깨달아서 흐름도 알게되고 보니 새로웠다. 이제 필수 구현 사항은 다한것같다. 내일은 에셋 새로 찾아보고 게임처럼 조금 다듬어봐야겠다.