유니티에서의 스레드는 동시에 접근하지않고 한번에 하나만 접근하기 때문에 C#에서 멀티스레드를 할때와 조금 다르다.
Update()함수가 아닌 곳에서 코드를 반복적으로 사용하고 싶을 때 코루틴을 사용할 수 있다.
그리고 Update()는 프레임마다 반복적으로 실행되기 때문에 몇초 동안 지연시키고 싶다면 60fps기준 초 * fps가 되어 엄청나게 실행될 것이다.
코루틴을 사용하면 일정 시간 원하는 만큼 실행할 수 있다.
게임 루프나 프레임 처리를 중단시키지 않으면서 긴 작업이나 반복적인 작업을 수행할 수도 있다
주로 애니메이션, 게임 로직, UI 업데이트 등을 처리하는 데 사용된다
코루틴 (Coroutine)
Unity의 Coroutine은 C# 언어의 IEnumerator 인터페이스를 구현하는 함수와 yield return을 사용한다.
이를 통해 지연 및 재개 가능한 함수를 작성할 수 있다.
IEnumerator MyCoroutine()
{
// Coroutine 시작 시 초기화 작업
while (/* 조건 */)
{
// Coroutine 반복 수행 시 처리할 작업
yield return null;
}
// Coroutine 종료 시 처리할 작업
}
Update와는 별개로 반복하는 루프 두개를 만들어보자.
시작하자마자 독립적으로 진행되는 병렬 루틴 2개를 생성하고 이때 병렬 루틴은 Coroutine을 사용한다.
CoroutineTest
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CoroutineTest : MonoBehaviour
{
public float intervalReading = 1f;
public int countReading = 0;
public float intervalMusicTime = 1f;
int countMusic = 0;
void Start()
{
StartCoroutine(coReading());
StartCoroutine(coMusic());
// 위아래 두개는 같다
//StartCoroutine("coReading");
//StartCoroutine("coMusic");
}
IEnumerator coReading()
{
while (true)
{
yield return new WaitForSeconds(intervalReading);
Debug.Log($"책을 읽는다 {countReading++}");
}
}
IEnumerator coMusic()
{
while (true)
{
yield return new WaitForSeconds(intervalMusicTime);
Debug.Log($"음악을 듣는다 {countMusic++}");
}
}
}
병렬로 진행하는 2개의 루틴을 진행했다.
유니티의 코루틴은 일반적인 스레드의 역할을 한다. (단 동기화는 하지 않아도 된다)
동시에 접근하는 것은 아니기 때문에 유니티 내부의 Single Thread가 각각의 코루틴을 진행시켜 주는 것이다.
코루틴으로 수직 및 수평으로 이동을 반복하는 게임 오브젝트 생성해보기
두 게임 오브젝트를 각각 하나는 수직, 하나는 수평방향으로 이동을 반복하는 코루틴의 예시를 만들어보자.
먼저 2D 방식으로 카메라를 보기위해 mainCamera에서 Projection을 Orthographic으로 바꿔준다.
CoroutineMoveManager라는 빈 게임오브젝트를 생성하여 두 오브젝트의 움직임을 관리할 스크립트를 넣어준다.
CoroutineMove
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CoroutineMove : MonoBehaviour
{
public Transform redCube;
public float limitXDist = 10f;
public float speedX = 10f;
int directionX = 1;
public Transform blueCube;
public float limitYDist = 4f;
public float speedY = 2f;
int directionY = 1;
void Start()
{
StartCoroutine(coMoveX());
StartCoroutine(coMoveY());
}
IEnumerator coMoveX()
{
while (true)
{
//yield return new WaitForEndOfFrame();
yield return null;
float x = speedX * directionX * Time.deltaTime;
redCube.Translate(Vector3.right * x);
if(redCube.position.x >= limitXDist ||
redCube.position.x <= -limitXDist)
{
directionX = -directionX;
}
}
}
IEnumerator coMoveY()
{
while (true)
{
//yield return null;
yield return new WaitForEndOfFrame();
float y = speedY * directionY * Time.deltaTime;
blueCube.Translate(Vector3.up * y);
if (blueCube.position.y >= limitYDist ||
blueCube.position.y <= -limitYDist)
{
directionY = -directionY;
}
}
}
}
yield return new WaitForEndOfFrame(); : 모든 Update()가 끝나고 프레임이 끝난후 호출된다
yield return null; : Update()후에 호출이 된다.
두가지의 yield return이 있는데, 여기 예제에서는 Update()문이 없기때문에 별 다른 차이없이 작동한다.
'개발 > Unity' 카테고리의 다른 글
[Unity] 씬, 씬 전환 [SceneManager, LoadScene] (1) | 2023.03.05 |
---|---|
[Unity] 유니티 메서드 접근, 데이터저장 [Method(public, private, static) , PlayerPrefs] (0) | 2023.03.04 |
[Unity] 레이캐스트, 레이저 충돌 [Raycast] (0) | 2023.02.27 |
[Unity] 프리팹의 복제와 재사용, Instantiate [Prefab, Instantiate] (0) | 2023.02.24 |
[Unity] 간단한 카메라 기법 [1인칭, 3인칭, FollowCamera, 백미러, Multi Camera] (1) | 2023.02.24 |