본문 바로가기
개발/Unity 내일배움캠프 TIL

Unity 코루틴(Coroutine)으로 딜레이 구현하기

by 석시 2023. 9. 14.



게임을 만들다보면 딜레이가 필요하다.

시전 모션이 끝나면 공격이 들어간다던지, 물리적인 판정 자체에 몇 프레임 씩 딜레이를 넣을수도 있다.

그러기 위해서 보통 코루틴을 사용한다.

인보크를 쓰면 안되나요? 라고 물어볼 수 있는데, 인보크 대신 코루틴을 사용하는 이유는 다음 게시글에 잘 정리되어 있다.

Unity 인보크(Invoke)와 코루틴(Coroutine) 정리
들어가며인보크 기본인보크 사용방법InvokeRepeatingCancelInvokeIsInvoking인보크 주의점코루틴코루틴 사용 방법StartCoroutineStopCoroutine 들어가며이번에 했던 프로젝트를 하고 나서, 가장 많이 느꼈던 점은 Invoke를 너무 남발한 거 같다는 점이다. 해당 함수 때문에 버그가 발생했을 때, 찾기도 버거웠을 뿐더러 (Invoke는 함수를 string으로 받기 때문에 참조 함수 목록에 들어가지 않게 된다.) 시전 타이밍을 스크립트의 코드 순서가 아닌 시간으로 정한다는 것이 게임을 구현하는데 있어 너무 불안요소였다. 따라서 이번에는 아예 Invoke에 대해 정리해보고 어느 때 쓰면 좋을지 알아보는 시간을 가지자. 인보크 기본인보크는 MonoBehaviour 클래스에서..
https://seoksii.tistory.com/21#45b722bc-8fc2-46e4-b6ca-1634b255614b


기본 형태

 
IEnumerator FunctionWithDelay()
{
  yield return null;
  // 딜레이 뒤로 원하는 기능을 작성
  Debug.Log("1프레임 있다가 호출!");
}
 

 
StartCoroutine(FunctionWithDelay);
 

다음과 같은 방식으로 선언한다.

반환값으로 반드시 IEnumerator를 해줘야한다.

호출은 StartCoroutine()을 이용한다.

yield return null은 함수 실행이 종료되었다가 1프레임 뒤에 바로 종료지점 다음부터 실행을 다시 시작한다.

해당 yield return을 여러 방식으로 바꿔서 다양한 종류의 딜레이를 구현할 수 있다.


물리 프레임으로 딜레이 주기

yield return null은 Update의 실행이 끝날 때마다 진입을 시작하는데, 그렇기 때문에 정확히 1프레임 뒤에 실행이 되는 것이다.

반대로 yield return new WaitForFixedUpdate()를 하게 되면 FixedUpdate가 끝날 때마다 진입을 한다.

즉, 물리 프레임으로 1만큼 뒤에 실행이 되는 것이다.

참고로 위 방법대로 하면 yield return을 할 때마다 new를 호출하기 때문에 약간의 성능 저하가 있을 수 있다.

때문에 해당 딜레이를 사용하기 위해선 new WaitForFixedUpdate()를 미리 호출해두어 저장해주자.

 
_wait = new WaitForFixedUpdate();

IEnumerator FunctionWithDelay()
{
  yield return _wait;
  // 딜레이 뒤로 원하는 기능을 작성
  Debug.Log("1 물리 프레임 있다가 호출!");
}
 

추가로 Update와 FixedUpdate의 구조가 어떻게 다른지 알고 싶다면 다음 글을 참고하자.

[내일배움단] Unity - Update() vs FixedUpdate()
이걸 글로 따로 정리하게 된 이유는 이해가 안갔던 상황이 너무 많았기 때문이다. 바로 Time.timeScale에 관한 부분이었다.강의에서 게임을 정지하기 위해 Time.timeScale = 0; 다음과 같이 timeScale을 0으로 만들어 줬는데, 어떤 건 정지하고, 어떤 건 정지하지 않고 여전히 움직이는 이상한 상황. 문제의 장면.빗방울과 타이머는 멈췄지만, 캐릭터는 멈추지 않았다.골때리는건, 내가 따라 만든 게임은 캐릭터도 멈춰있는 것이었다. 원인을 찾아보니 차이점이 있었다.강의에서 캐릭터의 움직임을 구현할 때는 Update() 함수를 사용하였고,내가 이것을 따라만들 때는 FixedUpdate() 함수를 사용하였던 것이다. 이걸 보고 바로 알 수 있는 점은, ”Time.timeScale은 Upda..
https://seoksii.tistory.com/12


시간으로 딜레이 주기

new WaitForSeconds(seconds)new WaitForSecondsRealtime(seconds)를 사용할 수 있다.

WaitForSeconds(seconds)는 게임 시간 기준으로 입력값만큼의 초를 기다렸다가 진입하고, WaitForSecondsRealtime(seconds)는 현실 시간 기준으로 기다린다.

둘이 다를 수가 있나요?라고 물어볼 수 있는데, Time Scale이 1이 아니면 둘의 시간이 서로 달라진다.

이에 대해서 위에 링크해놓은 글의 0. Time Scale 부분을 참고하자.

 
_wait = new WaitForSeconds(5f);

IEnumerator FunctionWithDelay()
{
  yield return _wait;
  // 딜레이 뒤로 원하는 기능을 작성
  Debug.Log("5초 있다가 호출!");
}
 


그 외의 다양한 딜레이들

new WaitForEndOfFrame() : 한 프레임의 화면 렌더링 작업이 끝나면 진입

startCoroutiune(string) : 입력한 이름의 코루틴이 끝나면 진입

yield return new www(string) : 해당 웹 통신 작업이 끝나면 진입

코루틴을 통해 게임 동작에 딜레이를 부여하고 시간이나 프레임 경과에 따른 상태 변화들을 부여할 수 있도록 하자.

3D 쿼터뷰 액션게임 - 코루틴으로 근접공격 구현하기 [유니티 기초 강좌 B43]
드디어 기다리던 메인 액션!😎 근접 공격을 구현해보는 시간이 되겠습니다. 이번 강좌에서 정말 중요한 '코루틴'도 다루니 꼼꼼히 살펴주세요! 📖 챕터 : 01 00:00 변수 생성 02 03:58 근접 공격 범위 03 05:30 근접 공격 효과 04 09:53 공격 로직 (코루틴) 05 17:26 공격 실행 #유니티기초 #유니티강좌 #유니티3D #쿼터뷰
https://youtu.be/Zfoyagdz1y0?si=eha0_vez-mCjIBNf


Uploaded by N2T