2017년 12월 18일 월요일

Unity - Scripting - C# - Coroutine


코루틴(Coroutine)


함수를 호출하면 반환값을 반환하기 전에 실행 완료됩니다. 즉, 함수에서 수행되는 작업은 하나의 프레임에서 수행된다는 것을 의미하고, 함수 호출은 절차적 애니메이션을 포함하거나 시간의 경과와 함께 일련의 이벤트에는 사용할 수 없습니다. 예를 들어, 오브젝트의 알파(투명도)가 완전히 투명해질 때까지 서서히 계속 감소하는 장면을 상정했다고 합시다.
void Fade() {
    for (float f = 1f; f >= 0; f -= 0.1f) {
        Color c = renderer.material.color;
        c.a = f;
        renderer.material.color = c;
    }
}

위의 상태에서 Fade 함수가 원하는대로 효과를 얻을 수 없습니다. Fade가 시각적으로 알 수 있게 하기 위해서 알파는 몇 프레임에 걸쳐 렌더링되는 중간값으로 변경 한 후 점점 감소할 필요가 있습니다. 그러나 위의 함수는 하나의 프레임에서만 실행됩니다. 중간값은 시각적으로 알 수 없고, 오브젝트는 순간적으로 투명해집니다.
Update 함수에 코드를 추가하는 것도 프레임마다 페이드 할 수 있습니다. 그러나 이러한 작업은 보통 코루틴을 사용하면 편리합니다.
코루틴은 실행을 중지하여 Unity에 제어권을 돌려주고, 그러나 계속할 때는 다음 프레임에서 중지한 곳부터 실행을 계속할 수 있는 기능입니다. C#에서 코루틴은 다음과 같이 선언합니다:
IEnumerator Fade() {
    for (float f = 1f; f >= 0; f -= 0.1f) {
        Color c = renderer.material.color;
        c.a = f;
        renderer.material.color = c;
        yield return null;
    }
}

즉, 이것은 IEnumerator 형식을 반환값으로 가지며 yield return 구문을 어디엔가 포함하고 있는 함수입니다. yield return 행은 실행을 중지하고 다음 프레임에서 실행을 재개할 수 있는 지점입니다. 코루틴을 실행하려면 StartCoroutine 함수를 사용합니다. \n
void Update() {
    if (Input.GetKeyDown("f")) {
        StartCoroutine("Fade");
    }
}

UnityScript에서는 좀 더 간단합니다. yield statement를 포함하는 함수는 코루틴으로 해석되어 IEnumerator 반환 형식은 명시적으로 선언될 필요가 없습니다:
function Fade() {
    for (var f = 1.0; f >= 0; f -= 0.1) {
        var c = renderer.material.color;
        c.a = f;
        renderer.material.color = c;
        yield;
    }
}

또한 UnityScript에서 코루틴을 시작하는 경우, 일반 함수와 동일하게 호출합니다:
function Update() {
    if (Input.GetKeyDown("f")) {
        Fade();
    }
}

Fade 함수의 루프 카운터는 코루틴의 라이프 사이클을 통해 올바른 값을 유지합니다. yield 중에 모든 변수 또는 파라미터가 올바르게 보존됩니다.
기본적으로 코루틴은 yield 한 직후의 프레임에서 재개되지만, 지연했다가 다시 시작하려면 WaitForSeconds 함수를 사용합니다:
IEnumerator Fade() {
    for (float f = 1f; f >= 0; f -= 0.1f) {
        Color c = renderer.material.color;
        c.a = f;
        renderer.material.color = c;
        yield return new WaitForSeconds(.1f);
    }
}

UnityScript에서는:
function Fade() {
    for (var f = 1.0; f >= 0; f -= 0.1) {
        var c = renderer.material.color;
        c.a = f;
        renderer.material.color = c;
        yield WaitForSeconds(0.1);
    }
}

이 방법으로 효과를 일정한 시간 범위에서 펼칠 수 있지만, 최적화 방법으로 해도 편리합니다. 게임 중의 태스크는 정기적으로 수행해야 하며, 간단한 방법은 Update 함수에서 할 수 있습니다. 그러나 이 함수는 초당 몇 번이나 호출됩니다. 작업이 너무 자주 반복할 필요가 없는 경우, 코루틴에 넣어 매 프레임 실행하지 않고 정기적으로 업데이트 할 수 있습니다. 예를 들자면, 적이 근처에 있는 것을 플레이어에게 알리는 알람입니다. 코드는 다음과 같습니다:
function ProximityCheck() {
    for (int i = 0; i < enemies.Length; i++) {
        if (Vector3.Distance(transform.position, enemies[i].transform.position) < dangerDistance) {
                return true;
        }
    }
    
    return false;
}

적이 많은 경우에 이 함수를 매 프레임 호출하여 현저한 오버 헤드를 초래할 지도 모릅니다. 그러나 코루틴을 사용하여 1/10 초 간격으로 호출할 수 있습니다:
IEnumerator DoCheck() {
    for(;;) {
        ProximityCheck;
        yield return new WaitForSeconds(.1f);
    }
}

따라서 게임에 악영향을 주지 않고 체크 횟수를 비약적으로 감소시킬 수 있습니다.

출처 : https://docs.unity3d.com/kr/current/Manual/Coroutines.html

출처 : http://theeye.pe.kr/archives/2725





댓글 없음:

댓글 쓰기

javascript - SQL 예약어 제거

  <script language="javascript"> //특수문자, 특정문자열(sql예약어) 제거 function checkSearchedWord(obj){ obj.value = obj.value+&quo...