코루틴의 단점 Programming


코드의 흐름이 한눈에 들어오게 의사코드 수준으로 짤수있어서 편했는데

막상 코루틴의 단점이 이제막 수면위로 드러나고 있다.

 1:  function 불꽃_이펙트의일생()
 2: 
 3:     local 핸들_이펙트 = 이펙트관리자_로딩( 불꽃 )
 4:
 5:     이펙트_플레이( 불꽃_생성 )
 6:
 7:     코루틴관리자_대기( 10초 )
 8:
 9:     이펙트_플레이( 불꽃_loop )
10:
11:    코루틴관리자_대기( 30초 )
12:
13:     이펙트_플레이( 불꽃_소멸 )
14:
15:     이펙트관리자_삭제( 핸들_이펙트 )
16: end


위의 예처럼 단순한 이펙트의 일생을 코루틴으로 짰다고 가정할때
불꽃이 현재 씬에 출력되어야 할것이다.

어느 유져가 내게 공격을 하고
바닥난 나의  피통을 보며 완전 다른 맵이나

헌데 게임의 상태가 바뀌어서 맵로딩이나 다른 씬으로 넘어갈때

내겐 이펙트가 터지며 위의 코루틴이 돌게 될것이다.
이때 화면을 전환하기 위해 돌고있던 코루틴의 리스트를 모두 제거해 버린다면
어떻게 될까?

11라인에서 30초동안 코루틴은 yield 상태다.
이때 코루틴 업데이트 리스트에서 빼버린다면
11라인 이후의 코드들은 더이상 돌지않게된다
코루틴핸들이 날아가버렸으니 사실상 resume 시켜주지않는(시켜줄수도없는)
죽은 코드가 되버린다.

메모리에 이펙트가 올라간채로 있을것이고 설령 이펙트 관리자에서 강제로 모든 이펙트를 삭제 시켜줄수있겠지만
이 셈플에서만 가능한 예일뿐이다.

생각해본 해결방법은
취소 가능한 레벨의 코루틴리스트를 따로 두고
그것들은 wait , pause 들은 강제로 돌려서 함수를 모조리 돌아가게 만드는 수밖에 없을듯하다.

그나마 해결한 방법은 최대한 방어적으로 짜는 수밖에 없다.

코루틴을 대기 시킬때 항상 도중에 cancel 되는 상황을 가정하고 만들어야 한다.







덧글

  • 몽상가 2015/02/04 09:36 # 삭제 답글

    해제 되어야 할 메모리 인스턴스들을 생성 시 마다 등록하고, 일괄적으로 해제한다면 좋지 않을 까요?
    마치 가비지 컬렉터 처럼 생성 시 모두 등록해 놓고 코루틴이 명백히 종료되거나, 취소 될 때 호출!
  • Little Wing soft 2015/02/04 17:56 #

    몽상가님 답변 감사드립니다.
    4년전 썼던 글이라 저도 무슨 상황에서 썼는지 기억이 가물가물 했습니다.
    덕분에 오랫만에 기억을 되살려봤네요.

    스스로 생각을 정리하던중에 쓴 글이다보니 부연설명이 빠졌는데요

    1. lua 스크립트 기반의 코루틴 스케쥴러 라는점.
    2. 코루틴의 대기상황 에서 빠져나올때 남아있는 코드를 모두 실행할것인지 여부.

    이 두가지가 핵심이었습니다.

    문제가 되던게, 현재 씬에서 다음 씬으로 넘어간다거나 하는 상황이 되어서
    현재씬에 관련된 Task를 모두 Kill 해야 할때였습니다.

    코루틴에서 빠져나오는 위치가 대부분 yield 인데요
    유니티의 코루틴 에서는 Stop 하게되면 WaitForSeconds 에서 바로 빠져나오게 되죠.
    그밑에 있는 코드들이 실행되지 않습니다.

    그러나 lua 에서는 yield 밑에 남아있는 코드가 실행됩니다.

    따라서 스케쥴러가 어떤 Task를 Kill 시킬때
    강제로라도 yield 밑의 코드들을 실행시켜야 할지 아니면
    return 할지 선택해야 하는지 고려해야 하는 상황이었습니다.

    yield 밑의 코드가
    단지 어떤 asset의 메모리 해제 뿐만이 아니라
    시간이 걸리는 일들( 현재씬에서 오브젝트 검색후 피격 에니메이션처리,
    http get, 서버응답결과연동 등등)
    이 오는 상황이 생겨서 이부분을 어떻게 해결할까 고민했던 글이었네요.





댓글 입력 영역