ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 코루틴 (Coroutine)
    유니티/유니티 코드 2024. 2. 14. 15:22

    <1. 코루틴이란>

    유니티에서 정말 중요한 역할을 하는 코루틴. 생각해보니 코루틴에 대해서도 확실하게 짚고 넘어간게 없어 정리해둔다

     

     

    Unity Documentation에 있는 사전적 정의이다. 사실상 가장 중요한 코루틴의 핵심 요소는 이 3가지로 정의 가능하다

     

    1. 작업을 다수의 프레임에 분산

    2. 실행을 중단한 부분에서 다음 프레임을 계속할 수 있는 메서드

    3. 시간의 흐름에 따른 이벤트의 시퀀스, 절차상 애니메이션 표현 가능

     

    이것만 봐서는 뭔가 이해가 될것 같으면서도 무슨 말인지 잘 모르겠다. 하지만 이 예시를 보자

    void Fade()
    {
        Color c = renderer.material.color;
        for (float alpha = 1f; alpha >= 0; alpha -= 0.1f)
        {
            c.a = alpha;
            renderer.material.color = c;
        }
    }

     

    색상의 알파를 0.1씩 내리면서 서서히 투명해지게 만드는 효과이다. 

    여기서 for문을 사용하게 되면 순차적으로 0.1씩 알파를 빼주는것은 맞지만

    0.1씩 빠지는 중간과정은 보여주지 않고 오로지 결과만을 단번에 보여주게 된다.

     

    하지만 우리가 원하는것은 서서히 색이 천천히 투명해지는 효과이기에 이 방법은 적절하지 않다

    <2. 코루틴 사용방법>

    IEnumerator Fade()
    {
        Color c = renderer.material.color;
        for (float alpha = 1f; alpha >= 0; alpha -= 0.1f)
        {
            c.a = alpha;
            renderer.material.color = c;
            yield return null;
        }
    }

     

     

    이번엔 코루틴을 사용하여 코드를 제작해보았다. 달라진점은 딱 두가지이다

     

    Fade() 메서드 앞 반환타입이 void 대신 IEnumerator가 붙은것

    가장 마지막 줄에 yield return null; 이 붙은것

     

    이 2가지만 달라졌는데도 우리가 원하는 서서히 투명해지는 효과를 얻어낼수 있다.

    그리고 이 2가지가 코루틴을 사용하기 위한 기본조건이다

     

    1. 무조건 반환타입은 IEnumerator 이다

    2. 반환문으로는 무조건 yield return 반환문을 사용한다

     

    여기서 yield return null 라인은 실행이 정지되고 다음 프레임에서 다시 시작되는 지점이다

     

    하지만 이건 어디까지나 메서드이다. 이 자체로는 실행이 불가능하고,

    코루틴을 시작하기 위해서는 StartCoroutine 함수를 사용한다

    이거 중요하다

     

    void Update()
    {
        if (Input.GetKeyDown("f"))
        {
            StartCoroutine(Fade());
        }
    }

     f키를 누르면 코루틴으로 제작된 Fade 메서드를 호출한다

     

    그럼 도대체 코루틴과 업데이트의 차이는 무엇일까? 왜 비슷한 업데이트를 두고 코루틴을 사용해야 하는걸까?

     

    바로 업데이트에 작성된 코드는 매 프레임마다 계속 반복적으로 실행되어 효율적이지 않을 수 있지만

    코루틴은 자신이 필요한 순간에만 반복하고, 필요하지 않은 경우에는 멈출수 있어 더 효과적이기 때문이다

     

    <3. 코루틴 기능 & 응용>

    이제 코루틴을 효과적으로 사용할 수 있는 다양한 기능들을 살펴보자

     

    우선 yield return의 반환값에 따라 일시정지, 재개에 대한 기준이 마련된다

    null 다음 프레임까지 일시 정지 후 재개
    new WaitForSeconds(float seconds) seconds만큼의 시간동안 정지 후 재개
    new WaitForSecondsRealtime(float seconds) seconds만큼의 시간동안 정지 후 재개, Time.timeScale의 변동 무시
    new WaitForEndOfFrame() 프레임을 화면에 표시하기 직전 즉, 모든 카메라 및 GUI를 렌더링한 후 프레임이 끝날 때까지 정지 후 재개
    new WaitForFixedUpdate() 다음 FixedUpdate 까지 정지 후 재개

     

    2번째 new WaitForSeconds(float seconds) 의 예시로 코드를 짜보겠다

    using System.Collections;
    using UnityEngine;
    using UnityEngine.UI;
    
    public class FadeCoroutine : MonoBehaviour
    {
        public Image image;
    
        void Start()
        {
            StartCoroutine(Fade());
        }
    
        IEnumerator Fade()
        {
            for (float f = 1f; f >= 0; f -= 0.1f)
            {
                Color c = image.color;
                c.a = f;
                image.color = c;
                yield return new WaitForSeconds(0.1f);
            }
        }
    }

    0.1초마다 이미지의 알파값을 0.1씩 낮추는 코드이다

     

    만약 Fade함수가 코루틴이 아닌 일반 함수였다면 서서히 투명해지는것이 아닌 즉시 투명해졌을 것이다

     

    한가지 더 예로 코드를 가져오겠다

    using System.Collections;
    using UnityEngine;
    using UnityEngine.UI;
    
    public class Coroutines : MonoBehaviour
    {
        const float delayTime = 2f;
    
        public void PressButton()
        {
            StartCoroutine(ChangeColor());
        }
    
        IEnumerator ChangeColor()
        {
            yield return new WaitForSeconds(delayTime);
    
            Color c = GetComponent<Image>().color;
            c.b = 0f;
            GetComponent<Image>().color = c;
        }
    }

     

    딜레이 타임은 2초. 버튼을 누르는순간 Changecolor 코루틴이 시작되고, 

    yield return 라인이 제일 윗줄에 있으니 우선은 2초동안은 아무런 변화가 일어나지 않는다

    그리고 버튼의 색이 노란색으로 바뀌는것을 볼수 있다

     

    만약 메 프레임마다 호출이 되는 Update() 메소드로 2초를 지연시키고 싶다?

    그럼 2 * 60 = 120번 Update() 메소드를 호출해야 한다.

     

    그렇다고 모든 순간에 코루틴을 사용하는것도 현명한 방법이 아니다. 가장 좋은 방법으로는

     

    별 다른 조건없이 무조건적인 반복이 필요한 경우에는 Update를,

    조건에 따라 멈추거나 지연을 원하는대로 넣으면서 반복할 경우에는 Coroutine을 사용한다

     

     

    '유니티 > 유니티 코드' 카테고리의 다른 글

    Vector3.Reflect  (0) 2024.03.19
    Collision.Contact[]  (0) 2024.03.19
    foreach  (0) 2024.02.14
    딕셔너리 (Dictionary)  (0) 2024.02.13
    리스트 (List)  (0) 2024.02.13
Designed by Tistory.