본문 바로가기
C#/Unity

유니티 코루틴: 시간에 따른 로직 구현과 스레드 비교

by GangDev 2024. 4. 19.

 

유니티의 코루틴은 여러 프레임에 걸쳐 작업을 수행할 수 있게 해주는 기능이다.

코루틴은 메서드 내에서 실행을 일시 중지하고, 다음 프레임에서 중단된 위치에서 계속 실행할 수 있다.

이는 프로시저럴 애니메이션이나 시간에 따른 이벤트 시퀀스를 포함하는 메서드 호출과 같은 상황에서 유용하다.

 

코루틴은 IEnumerator 타입의 반환 값을 가진 메서드로 작성된다.

코루틴 내에서는 yield return 문을 사용하여 코드의 실행을 일시 중지하고, 다음 프레임에서 계속 실행할 수 있다.

IEnumerator MyCoroutine()
{
    // 코드 실행
    yield return new WaitForSeconds(1); // 1초 대기
    // 대기 후 계속 실행
}

 

코루틴을 시작하기 위해서는 StartCoroutine 메서드를 사용한다.

이 메서드는 코루틴 메서드의 이름을 문자열로 받거나, 코루틴 메서드의 인스턴스를 받을 수 있다.

StartCoroutine(MyCoroutine());

 

코루틴을 중지하기 위해서는 StopCoroutine 메서드를 사용한다.

이 메서드는 코루틴 메서드의 이름을 문자열로 받거나, 코루틴 메서드의 인스턴스를 받을 수 있다.

StopCoroutine(MyCoroutine());

 

코루틴 내에서 yield return 문을 사용하여 코드의 실행을 일시 중지하고, 특정 조건이 충족될 때까지 기다릴 수 있다.

예를 들어, WaitForSeconds를 사용하여 특정 시간 동안 코드의 실행을 일시중지할 수 있다.

IEnumerator MyCoroutine()
{
    // 코드 실행
    yield return new WaitForSeconds(1); // 1초 대기
    // 대기 후 계속 실행
}

 

코루틴은 게임 로직을 여러 프레임에 걸쳐 실행하는 데 유용하며, 특히 시간에 따른 이벤트 시퀀스나 프로시저럴 애니메이션을 구현할 때 매우 효율적이다.

하지만 코루틴은 스레드가 아니므로, 코루틴 내에서 실행되는 동기 연산은 여전히 메인 스레드에서 실행된다.

따라서 메인 스레드에서 많은 CPU 시간을 소비하고 싶지 않다면, 코루틴 내에서 블로킹 연산을 피해야 한다.

 

예시 >>

플레이어 캐릭터가 화면에 나타나고, 일정 시간 동안 대기한 후에 사라지는 애니메이션을 구현해 보겠다.

using UnityEngine;
using System.Collections;

public class PlayerAppearDisappear : MonoBehaviour
{
    public GameObject player; // 플레이어 캐릭터 오브젝트

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

    IEnumerator PlayerAnimation()
    {
        player.SetActive(true); // 플레이어 캐릭터 활성화
        yield return new WaitForSeconds(3); // 3초 대기
        player.SetActive(false); // 플레이어 캐릭터 비활성화
    }
}

 

코루틴과 스레드의 차이점

유니티의 코루틴과 스레드는 게임 개발에서 비슷한 목적을 가지고 있지만, 실행 방식과 사용 목적에서 차이점이 있다.

 

코루틴 >>

* 실행 방식: 코루틴은 메인 스레드에서 순차적으로 실행된다. 코루틴은 yield return 문을 사용하여 실행을 일시 중지하고, 다음 프레임에서 계속 실행할 수 있다.

* 유니티 함수 사용: 코루틴 내에서 대부분의 유니티 기능을 안전하게 사용할 수 있다. 코루틴은 유니티 엔진이 제어하는 상태에서 실행되므로 데드락, 경쟁 조건, 또는 컨텍스트 스위치 등의 실제 멀티스레딩 문제를 걱정할 필요가 없다.

* 디버깅: 코루틴은 유니티의 메인 루프 내에서 실행되므로, 디버깅이 용이하다.

 

스레드 >>

* 실행 방식: 스레드는 별도의 스레드에서 병렬적으로 실행된다. 이는 CPU의 여러 코어를 활용하여 병렬 처리를 가능하게 한다.

* 유니티 함수 사용: 스레드 내에서 유니티 기능을 사용하려면 주의가 필요하다. 유니티 기능은 메인 스레드에서만 안전하게 호출될 수 있으며, 스레드 간 통신은 안전한 데이터 컨테이너를 사용하여 이루어져야 한다.

* 동기화 문제: 스레드는 다른 스레드가 언제든지 데이터를 변경할 수 있으므로, 데이터 동기화 문제를 해결해야 한다. 이는 데드락, 경쟁 조건 등의 문제를 초래할 수 있다.

 

차이점 요약 >>

실행 스레드: 코루틴은 메인 스레드에서 순차적으로 실행되며, 스레드는 별도의 스레드에서 병렬적으로 실행된다.

유니티 기능 사용: 코루틴 내에서 대부분의 유니티 기능을 안전하게 사용할 수 있지만, 스레드 내에서는 주의가 필요하다.

디버깅 및 병렬 처리: 코루틴은 디버깅이 용이하며, 병렬 처리를 지원하지 않는다. 스레드는 병렬 처리를 지원하지만, 복잡한 동기화 문제를 해결해야 한다.

 

코루틴과 스레드는 각각 다른 목적과 사용 목적에 따라 적절하게 사용되어야 한다.

코루틴은 게임 로직을 여러 프레임에 걸쳐 실행하는 데 유용하며, 스레드는 CPU 코어를 최대한 활용하여 병렬 처리를 수행하는 데 사용된다.

 

 

코루틴과 스레드 사용 예시

유니티 게임 개발에서 코루틴과 스레드는 각각 다른 상황에서 사용된다.

 

코루틴 >>

* 비동기 또는 시간에 따른 행동: 코루틴은 비동기 또는 시간에 따른 행동을 처리하는 데 유용하다. 예를 들어, 플레이어 캐릭터가 화면에 나타나고, 일정 시간 동안 대기한 후에 사라지는 애니메이션을 구현할 때 코루틴을 사용할 수 있다.

* 실행 시간 관리: 코루틴은 실행 시간을 관리하는 데 유용하다. 예를 들어, 특정 조건이 충족될 떄까지 대기하거나, 일정 시간 동안 대기하는 로직을 구현할 때 코루틴을 사용할 수 있다.

* 유니티 기능 사용: 코루틴 내에서 대부분의 유니티 기능을 안전하게 사용할 수 있다. 코루틴은 유니티의 메인 게임 루프 내에서 실행되므로, 데드락, 경쟁 조건, 또는 컨텍스트 스위치 등의 실제 멀티스레딩 문제를 걱정할 필요가 ㅇ벗다.

 

스레드 >>

* 병렬 처리: 스레드는 CPU의 여러 코어를 활용하여 병렬 처리를 가능하게 한다. 이는 게임에서 복잡한 계산이나 데이터 처리 등을 빠르게 처리하는 데 사용될 수 있다.

* 독립적인 작업: 스레드는 독립적인 작업을 처리하는 데 유용하다. 예를 들어, 네트워크 통신, 파일 I/O, 복잡한 계산 등을 별도의 스레드에서 처리할 수 있다.

* 스레드 간 통신: 스레드 간 통신이 필요한 경우에는 스레드를 사용하는 것이 적합하다. 에를 들어, 여러 스레드에서 계산된 결과를 하나의 슬데ㅡ에서 집계하는 경우에는 스레드를 사용할 수 있다.