오늘 꾸준실습 스터디를 하면서도 사용했고 지금 진행중인 팀 프로젝트에도 많이 사용한
코루틴에 관한 내용을 다뤄볼까 한다.
사용은 하는법은 알겠는데 뭐 사실 손에 익지 않아서 적는것도 있고, 더 잘쓰기위해 그리고
정확한 작동 원리도 궁금하고해서 자세히 파헤쳐보기로했다.
코루틴( Coroutine )은 주로 시간을 기반하거나, 애니메이션, 특정조건이 만족되는것을 기다릴때 사용한다고 한다.
코루틴을 이용한 예시들을 살펴보자 !
많은 예시를 보는것은 정말 매우 큰 도움이 된다. 이 예시들을 기억하지 않더라도 아 이렇게 연결해서 사용하면 되겠구나 생각을 하고 찾아보고 사용하면 되기 때문이다.
public class CoroutineExample : MonoBehaviour
{
private void Start()
{
StartCoroutine(WaitAndPrint());
}
private IEnumerator WaitAndPrint()
{
Debug.Log("잠깐 생각을 하지 기다려주겠나 ?...");
yield return new WaitForSeconds(3f);
Debug.Log("알겠네.. 그렇게 하도록 하지..(퀘스트가 완료되었습니다.)");
}
}
이건 메세지에 관한 예시라서 와닿지 않을 수 있다 계속해서 예제들을 살펴보자
public class EnemySpawner : MonoBehaviour
{
public GameObject enemyPrefab;
public float spawnInterval = 2f;
private void Start()
{
StartCoroutine(SpawnEnemies());
}
private IEnumerator SpawnEnemies()
{
while (true)
{
Instantiate(enemyPrefab, transform.position, Quaternion.identity);
yield return new WaitForSeconds(spawnInterval);
}
}
}
위 코드는 Enemy의 생성주기를 설정하여 2초마다 생성하는 코드이다.
이번엔 나도 처음보는 구조이다. ! 꽤 아니 매우 유용하게 사용가능한 예제를 보여주겠다
public class WaitForPosition : MonoBehaviour
{
public Transform player;
public Vector3 targetPosition;
private void Start()
{
StartCoroutine(WaitUntilPlayerReachesPosition());
}
private IEnumerator WaitUntilPlayerReachesPosition()
{
while (Vector3.Distance(player.position, targetPosition) > 1f)
{
yield return null;
}
Debug.Log("축하합니다 ! 목표에 도달하셨습니다 !!");
}
}
이런식으로 사용이 가능하다
(이외에도 시간에 따라 캐릭터가 부드럽게 이동하게만드는 경우도 있다고 한다. 이부분은 아직 이해를 못했다.
Vector3.Lerp를 이용하여 시간에 따라 부드럽게 오브젝트가 이동한다고 하는데, 아마 캐릭터의 움직임이 아니라 오브젝트를 움직여야하는 상황에 자연스럽게 움직이게 할 때 사용하는 것 같다. 직접 사용해봐야 정확한 차이를 알 수 있을것으로보임)
결국 이렇게 생각하면 된다 코루틴은 반복문을 응용하는것이다 !
A가 특정 조건을 만족했을때 B를 주고싶은데 ? 라는 상황에 깔끔하게 사용이 가능한 기능이다.
특정조건을 만족한다가 버프를 주고 시간이 끝나면 뺏고싶은데 ? 도 가능하다는것이다.
물론 이런 장점이 있지만 단점도 있다.
코루틴을 많이 사용하면 메모리 관리가 어려울 수 있다고 한다. 결국에는 루프문이기때문에 너무 많은 코루틴을 동시에 사용하게된다면 성능적으로 문제가 생길 수 있다.
또한 코루틴은 yield return 이 호출된 이후에도 메서드의 나머지 부분을 기억하고 있다고 한다. 이로인해 메모리 누수를 조심해야한다고 한다.
그러니까 바로 위의 예제에서도 플레이어가 목표한곳에 도달하지 않으면, 계속해서 코루틴이 작동하고 있는다는것이다.
이런 상황을 매~~~~~~~~우 조심해야한다는것이다. 이런 경우에 우리가 예외처리를 하듯이 시간안에 도달하지않으면 타임아웃을 시켜버리는것이다 !
public class WaitForPosition : MonoBehaviour
{
public Transform player;
public Vector3 targetPosition;
public float timeout = 10f; // 최대 대기 시간 (초)
private void Start()
{
StartCoroutine(WaitUntilPlayerReachesPosition());
}
private IEnumerator WaitUntilPlayerReachesPosition()
{
float elapsedTime = 0f;
// 플레이어가 목표 위치에 도달하거나, 타임아웃이 지나면 코루틴 종료
while (Vector3.Distance(player.position, targetPosition) > 1f && elapsedTime < timeout)
{
elapsedTime += Time.deltaTime;
yield return null; // 다음 프레임까지 대기
}
if (elapsedTime >= timeout)
{
Debug.Log("타임아웃 발생: 플레이어가 목표에 도달하지 못했습니다.");
}
else
{
Debug.Log("축하합니다! 목표에 도달하셨습니다!");
}
}
}
이런식으로 반복문을 탈출할 여지를 만들어주는것이 좋다.