Unity Chapter 5-8. C# 프로그래밍 [중급] (1/2) : 코루틴 함수

Date:     Updated:

카테고리:

태그:

인프런에 있는 이제민님의 레트로의 유니티 C# 게임 프로그래밍 에센스 강의를 듣고 정리한 필기입니다. 😀
🌜 [레트로의 유니티 C# 게임 프로그래밍 에센스] 강의 들으러 가기!


Chapter 5. C# 프로그래밍 : 중급 (1/2)


코루틴 함수

  • 유니티가 지원하는 기능으로
    1. 처리와 처리 사이에 대기 시간을 넣어줌
    2. 여러 처리를 동시에 병렬로 할 수 있도록 해줌
    • 실제로 병렬 처리가 이루어 지는 것은 아님.
    • 빠르게 왔다 갔다 하면서 실행되서 병렬 처리 되는 것처럼 보여짐.


1. 대기 시간 : Fade in, Fade out 효과

  1. Hierarchy창에서 UI - Image 를 생성해준다.
    • 이름은 “Fade”
  2. Anchor Presets 에서 맨 오른쪽 하단에 있는 stretch-strectchAlt키를 누른 상태에서 선택해주자
    • UI 이미지가 화면 한가득 채워진다.
  3. Image 컴포넌트에서 Color 값의 알파 A 값을 조절하여 Fade in, Fade out 효과를 줄 것이다.
    • 알파 값이 높을 수록(255) 불투명, 알파 값이 낮을 수록(0) 투명.
  4. 새로운 📜Fade.cs 스크립트를 만들어서 이 UI에 붙여준다.

📜Fade.cs

  • Image컴포넌트로 부터 Color의 알파값(a)을 가져와 Fade in, Fade out 효과를 만들어 볼 것이다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; // Image 컴포넌트를 가져오기 위해 해주어야 한다.

public class Fade : MonoBehaviour
{
    public Image fadeImage; // 이미지 컴포넌트. 

    void Start()
    {
        FadeIn();
    }

    void FadeIn()
    {
        Color startColor = fadeImage.color;

        for(int i = 0; i < 100; i++)
        {
            startColor.a = startColor.a - 0.01f;
            fadeImage.color = startColor;
        }
    }
}
  • using UnityEngine.UI
    • Image 컴포넌트를 가져오기 위해 필수로 적어주어야 한다.
  • public Image fadeImage;
    • 이미지 컴포넌트. (슬롯으로 연결시켜줄 것)
    • UnityEngine.UI에 있다.
  • `void FadeIn() 함수
    • startColor.a = startColor.a - 0.01f;
      • 이미지 컴포넌트의 알파값을 0.01f만큼 빼준다.
        • 1.0f는 100 %, 즉 255를 의미한다.
        • 0.01f는 1 %.
      • for문 반복문 안에서 알파값을 점점 1%씩 줄여 투명하게 만든다
        • fadeImage.color = startColor;
        • 점점 부드럽게 투명해진다.

이미지 컴포넌트 fadeImage 변수 슬롯에 드래그 앤 드롭 해주는거 잊지말기!!

그러나 위와 같은 코드를 실행시키면 서서히 투명해지는게 아니라 눈깜빡할 새에 한번에 투명해져버린다. 요즘 컴퓨터는 성능이 좋아 for문 100번 정도는 눈깜빡할 새에 끝내기 때문이다.

코루틴을 사용하여 알파 값을 줄이고 난후 대기하고 줄이고 대기하고를 반복하면 된다.

  • 일반적인 함수
    • 일직선 상으로 return을 만들 때까지 그냥 쭉 실행된다
  • 코루틴 함수 ✨✨
    • 코루틴은 C# 정식 문법이 아니다. 유니티만의 문법이다.
    • IEnumerator라는 타입을 리턴한다.
    • ✨✨함수 바디 코드를 쭉 저리하다가 yield return 시간문을 만나면 해당 시간만큼 대기하고 함수 밖을 빠져나가 다른 일을 한다. 그리고 정해진 시간이 지나면 yield문 위치로 다시 돌아와 그 아래 코드를 실행한다.✨✨
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; 

public class Fade : MonoBehaviour
{
    public Image fadeImage; 

    void Start()
    {
        StartCoroutine(FadeIn());
    }

    IEnumerator FadeIn()
    {
        Color startColor = fadeImage.color;

        for(int i = 0; i < 100; i++)
        {
            startColor.a = startColor.a - 0.01f;
            fadeImage.color = startColor;

            yield return new WaitForSeconds(0.01f);
        }
    }
}
  • IEnumerator FadeIn()
    • FadeIn은 이제 IEnumerator 타입을 리턴하는 코루틴 함수 다.
    • 한번 알파값을 줄이고나서 yield return new WaitForSeconds(0.01f);0.01초 만큼 대기한다.
      • new WaitForSeconds 대기 시간 오브젝트를 생성.
      • for문 100번 도니까 0.01초 * 100 해서 총 1초가 걸린다

코루틴 함수 실행하는 방법 : StartCoroutine()

StartCoroutine() 함수 안에 매개변수로서 코루틴 함수를 넣어 주어야 실행할 수 있다.

  • StartCoroutine( FadeIn() )
    • 함수 호출 형태로 넣어주는 방식.
    • 성능은 좋지만 인위적으로 멈출 순 없다.
  • StartCoroutine( "FadeIn" )
    • 함수 이름을 문자열로 넣어주는 방식
    • 코루틴을 시작하고 인위적으로 멈출 수 있다.
      • StopCoroutine("FadeIn") 라는 함수로 해당 함수 강제 종료가 가능하다.
  • 수동으로 종료가 되느냐 안되느냐의 차이.


2. 병렬 처리 : 비동기적 실행

  1. 빈 오브젝트를 만든 후
  2. 📜HelloCoroutine.cs 를 만들어 붙여준다.

📜 HelloCoroutine.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class HelloCoroutine : MonoBehaviour
{
    void Start()
    {
        StartCoroutine("HelloUnity");
    }

    IEnumerator HelloUnity()
    {
        Debug.Log("Hello");

        yield return new WaitForSeconds(3f); // 3초 대기

        Debug.Log("Unity");
    }
}
  • “Hello”가 출력된 후 3초 뒤에 “Unity” 출력

코루틴 함수를 동시에 2개 돌리면 어떻게 될까?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class HelloCoroutine : MonoBehaviour
{
    void Start()  // 코루틴 함수 2개 실행
    {
        StartCoroutine("HelloUnity");
        StartCoroutine("HiCSharp");
        Debug.Log("End");
    }

    IEnumerator HelloUnity() // 코루틴 함수 1
    {
        Debug.Log("Hello");

        yield return new WaitForSeconds(3f); 

        Debug.Log("Unity");
    }

    IEnumerator HiCSharp() // 코루틴 함수 2
    {
        Debug.Log("Hi");

        yield return new WaitForSeconds(5f); 

        Debug.Log("CSharp");
    }
}
  • 직관적으로 생각했을 때
    • HelloUnity() 코루틴 함수가 실행을 끝내는데 총 3초, HiCSharp()코루틴 함수가 실행을 끝내는데 총 5초 이렇게 해서 총 8초가 걸릴 것 같다.
    • Hello - Unity - Hi - CSharp - End 순으로 출력될 것 같다.
  • 그러난 실제로는
    • Hello - Hi - End - Unity - CSharp 순으로 출력된다.
    • Hello - Hi - End 까지 출력한 다음에 이를 기준으로
      • 3초 뒤 Unity 출력
      • 5초 뒤 CSharp 출력

image

  • 이와 같은 현상이 일어나는 이유는 코루틴 함수가 비동기 방식으로 실행되기 때문이다.
    • 일반 함수의 경우 동기 방식
      • A 함수가 끝나면 그 끝난 시점에 맞춰서, 즉 끝난 시점에 sync를 맞춰서 B 함수가 실행되는 식
    • 코루틴 함수의 경우 비동기 방식
      • A 함수가 시작되자마자 바로 B함수가 실행됨. B함수가 실행되자마자 바로 C함수가 실행됨.
      • 각 함수의 끝나는 시점은 중요하지 않다. 시점을 맞추지도 않는다. B함수는 A함수가 끝나기를 기다리지 않는다.
      • 병렬 처리! 동시에 여러 작업을 돌리 수 있다.
    • StartCoroutine("HelloUnity")를 시작 하자마자 바로 StartCoroutine("HiCSharp")도 시작한다. 그리고 바로 이어 Debug.Log("End")가 실행된다.
      • 각 서로의 함수가 끝나는 시점을 기다리지 않고 그냥 바로 뒤이어 시작해버린다.
        • 따라서 만약에 HelloUnity함수에서 무한 루프에 갇혔다고 가정해보면 동기적 실행 방식에선 HiCSharp 함수는 영원히 실행되지 못하지만 비동기적 실행 방식에선 그냥 뒤이어 HiCSharp이 바로 실행된다. HelloUnity 함수가 끝나는 시점에 실행되는게 아니라 그냥 HelloUnity가 시작되면 바로 뒤이어서 실행되기 떄문에.


yield return null

yield return null

대기 시간을 null로 해주면 딱 한프레임 쉰다. 즉 60프레임이라면 1/60초 쉼.



🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우 
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄

맨 위로 이동하기

Unity Lesson 1 카테고리 내 다른 글 보러가기

댓글 남기기