[Unity] 코루틴 함수에 대해 알아보자

조팽이·2024년 4월 5일

Unity

목록 보기
6/13

유니티를 접하고 처음 맞닥들이는 어려움이 바로 코루틴 함수였다.

코루틴 함수란?

코루틴 함수는 Update함수의 서브 루틴이라고 생각하면 이해하기가 쉽다. 이 점만 이해한다면 다루는 것이 어렵지 않다. Update함수는 매 프레임마다 실행된다. 대부분의 게임에선 이 Update함수 안에서 많은 구현들을 하게 되는데, 이 구현 코드가 길어져 방대해지거나, 로직이 어려워지는 경우가 발생할 수 있다. 이 때 코루틴 함수를 써서 1. 서브 루틴을 실행시키거나 2.Update함수와 티키타카를 통해 원하는 루틴을 동작시킬 수 있다.

예시를 보기전 코루틴 함수의 정확한 작동 원리를 살펴보자. 유니티 공식 래퍼런스에 이렇게 적혀있다.

일반적인 코루틴 업데이트는 Update 함수가 반환된 후 실행됩니다. 코루틴은 주어진 YieldInstruction이 완료될 때까지 실행을 중단(양보)할 수 있는 함수입니다. 코루틴의 다른 사용법은 다음과 같습니다.

yield 코루틴은 모든 Update 함수가 다음 프레임에 호출된 후 계속됩니다.
yield WaitForSeconds 지정한 시간이 지난 후, 모든 Update 함수가 프레임에 호출된 후 계속됩니다.
yield WaitForFixedUpdate 모든 FixedUpdate가 모든 스크립트에 호출된 후 계속됩니다.
yield WWW WWW 다운로드가 완료된 후 계속됩니다.
yield StartCoroutine 코루틴을 연결하고 MyFunc 코루틴이 먼저 완료되기를 기다립니다.

이게 영어 단어 yield의 뜻인 양보를 생각하면 이해가 편하다. 코루틴 함수내에서 yield return을 통해 null, new WaitForSeconds(3f)등을 호출 할 수 있는데, yield return null의 뜻은 유니티 제어권을 한 프레임만큼 Update함수한테 양보하고 다시 가져와서 밑의 코드를 실행한다는 의미이며 yield return new WaitForSeconds(3f)는 3초만큼 양보하고 yield 밑의 코드를 실행한다는 의미이다. 코드를 보자.

bool isDelay = false;
float delayTime = 3f;
float timer = 0f;
void Update(){
	if(Input.GetKeyDown(KeyCode.Space)){
    
    	if(!isDelay){
        	isDelay = true;
       		//스킬 구현
        	
        }
    	
        if(isDelay){
        	timer+= Time.deltaTime;
            if(timer > delayTime){
            	timer = 0f;
                isDelay = false;
            
            }
        		
        }
    
    }


}

위의 코드는 스킬 delay를 구현하는 간단한 코드이다. 스킬이 나가고 delayTime만큼이 지나고 다시 스킬이 나갈 수 있다. 이 코드를 coroutine함수를 사용하여 바꿔보면 다음과 같이 간단히 바꿀 수 있다.

bool isDelay = false;
float delayTime = 3f;
float timer = 0f;
void Update(){
	if(Input.GetKeyDown(KeyCode.Space)){
    
    	if(!isDelay){
        	isDelay = true;
       		//스킬 구현
        	StartCoroutine(AttackDelay(delayTime));
        }
    	
        
        
    
    }


}

IEnumerator AttackDelay(float delayTime){
	yield return new WaitForSeconds(delayTime);
	isDelay = false;
}

StartCoroutine함수를 통해 코루틴함수를 호출할 수 있으며 파라미터값도 넘겨줄 수 있다. 이 코드는 스킬이 구현되고 AttackDelay라는 코루틴함수가 호출되며 delayTime만큼 제어권을 넘겨주고 그 후 다시 제어권을 넘겨받아 isDelay = false; 문장을 수행한다. Update문이 간결해졌으며 위에서 말한 코루틴 역할 중 1. 서브루틴을 실행시킨다. 의 역할을 수행했다고 볼 수 있다. 이번엔 2. Update문과 티키타카 예시를 한번 보겠다.

using System.Collections;
using System.Collections.Generic;
using UnityEditor.Build;
using UnityEngine;
using UnityEngine.UI;
public class FadeScript : MonoBehaviour
{
    public Image panel;
    float time = 0f;
    float F_time = 2f;
    public bool isTitle = false;
    void Start() {
        if(!isTitle) StartCoroutine(FadeFlow());
    }
    public void Fade() {
        StartCoroutine(FadeFlow());
    }

    IEnumerator FadeFlow() {
        panel.gameObject.SetActive(true);
        Color alpha = panel.color;
        while (alpha.a > 0f) {
            time += Time.deltaTime / F_time;
            alpha.a = Mathf.Lerp(1, 0, time);
            panel.color = alpha;
            yield return null;
        }
        panel.gameObject.SetActive(false);
        yield return null;
    }
}

위는 실제로 Fadeeffect를 만들때 내가 사용했던 코드이다. FadeFlow 코루틴 함수를 보면 while문 마지막에 yield return null이 있는 것을 알 수 있다. 만약 FadeFlow함수를 코루틴이 아니라 일반 함수로 사용했다면 FadeEffect를 연출할 수 없을 것이다. 이유는 유니티의 제어권을 while문이 독점해서 while문 구문을 재빠르게 실행버리기 때문에 천천히 알파값이 줄어드는 것이 아니라 우리 눈에는 빛의 속도로 줄어버리기 때문이다. 따라서 코루틴 함수로 만들고 while문 마지막에 yield return null을 수행하여 제어권을 넘겨주고 다시 받고를 반복하여 자연스럽게 알파값이 줄어드는 것을 연출할 수 있다. 만약 이 스크립트에 Update문이 존재하고 Update문에서 A라는 행동을 한다면 A -> Fade -> A -> Fade 이렇게 티키타카하거나 다른 스크립트의 Update 구문과 티키타카를 하게 되기 때문에 2. Update문과 티키타카 한다고 볼 수 있다.

첫번째 예시 출처 : 베르의 게임개발 유튜브 코루틴 다루기(1)

profile
게임개발자

0개의 댓글