2010-08-09 3 views
10

이 방법을 (Unity C# 스크립트 내에서) 얻었지만 "yield"파트가 실제로 어떻게 작동하는지 이해하지 못합니다."yield"기능을 가진이 기능은 어떻게 세부적으로 작동합니까?

MSDN에서이 함수가 IEnumerator를 반환 할 것이라고 알고 있지만이 코드는 1.5 초 동안 기다리지 만 iterated를 얻지 못합니다. 이는 내부에서 만들어진 개체가 여러 번 만들어 졌기 때문입니다. 이 코드의 작동 방식을 설명 할 수있는 사람은 누구입니까? yield 한 번 사용하는 경우에는 하나 개의 요소와 함께있는 IEnumerator를 반환하는 것처럼

IEnumerator DestroyShip() 
{ 
    // create new gameobject 
    Instantiate(ExplosionPrefab, transform.position, transform.rotation); 
    // make current gameobject invisible 
    gameObject.renderer.enabled = false; 
    // set new position for the current gameobject 
    transform.position = new Vector3(0f, transform.position.y, transform.position.z); 
    // wait for 1,5 seconds 
    yield return new WaitForSeconds(1.5f); 
    // make the current gameobject visible again 
    gameObject.renderer.enabled = true; 
} 
+0

질문 제목이 더 이해하기 쉽습니다. 그래도 Google은 여전히 ​​키워드를 선택했습니다. – ftvs

답변

21

로 항복 수익을 apear 사용합니다. 일단.

컴파일러는 MoveNext() 함수와 Current 속성이있는 IEnumerator를 구현하는 클래스를 생성합니다. 클래스에는 호출간에 함수 상태를 저장하는 데 필요한 모든 멤버가 있습니다. 정확한 세부 사항은 "컴파일러 매직"으로 간주 될 수 있습니다.

이 생성 된 클래스의 객체는 Unity3d Engine에 의해 처리되고 관리됩니다. Unity3d 엔진은 매 프레임마다 한 번씩 각 활성 코 루틴에서 MoveNext()를 호출합니다 (달리 지시되지 않는 한).

이로 인해 Unity3d 프로그래머는 한 번에 한 프레임 씩 재생되는 스크립트를 작성할 수있었습니다. C# 컴파일러 마술과 Unity3d Engine 마술의 조합은 매우 강력하지만 사용하기 쉬운 스크립팅을 제공합니다.

질문에 대답하십시오 : 함수의 코드는 한 번 실행되지만 'yield return'문에서 일시 중지됩니다.

위에서 언급 한 것처럼 IEnumerator를 구현하는 특수 개체는 C# 컴파일러에서 만들어집니다.

MoveNext()에 대한 첫 번째 호출에서 함수는 폭발을 생성하고 현재 개체를 "new WaitForSeconds (1.5f)"로 설정합니다.

Unity3d 엔진은이 개체를 검사하여 특수 클래스 "WaitForSeconds"의 인스턴스이므로 대기열에 대기열을 넣고 1.5 초가 경과 할 때까지 두 번째 요소를 요청하지 않습니다. 그 동안 많은 프레임이 렌더링되고 폭발이 재생됩니다.

1.5 초 후에, Unity는 큐에서 열거자를 grap하고 MoveNext()를 다시 호출합니다. 함수의 두 번째 부분은 이제 실행되지만 두 번째 객체를 생성하지 못합니다. MoveNext()는 false를 반환하여 새로운 요소를 가져 오지 못했음을 나타냅니다.이 요소는 Unity3d에서이 열거자를 버리는 신호입니다. 가비지 콜렉터는 어느 시점에서 메모리를 회수합니다.

다음과 같이 : 많은 컴파일러와 Unity3d 마법이 진행되고 있습니다. 각 수익률 반환 명세서에서 다음 프레임까지 함수가 유지 될 것이라는 것을 기억하는 한 이러한 특수 함수의 이점을 충분히 누릴 수 있습니다.

+0

독립 실행 형 C# 프로젝트에이 코드를 작성하고 ILSPy에서 생성 된 .net 어셈블리를 살펴보면 모든 마법이 어떻게 작동하는지 신속하게 알 수 있습니다. –

5

, 그것은 당신이 그것을 반복하지 않는다는 인상을, 그 이유이다.

yield 키워드가 다소 이상하게 사용 되었기 때문에 전체 구문을 보지 않고 구현 된 이유를 이해하기 어렵습니다.

+1

"StartCoroutine"이라는 함수에서 호출됩니다. Unity.StartCoroutine (DestroyShip), 유니티 엔진 http://unity3d.com에 매우 특정한 것 같습니다. –

+0

참조 : http://unity3d.com/support/documentation /ScriptReference/MonoBehaviour.StartCoroutine.html –

+1

알겠습니다 ... 음, Unity 엔진의 컨텍스트에서 확실합니다. –

1

IEnumerable보다는 IEnumerator을 사용하는 것이 더 편하고 사용하기 쉽기 때문에 더 좋습니다. IEnumerable<T>을 사용하는 것이 더 좋습니다. yield return은 iterator 블록을 구현하기위한 문법적 설탕 일 뿐이며 컴파일러는 프로그램 적으로 쉽게 생성 할 수있는 표준 보일러 플레이트이므로 관련 코드를 생성합니다. 당신은 하나의 일련의 작업을 할 때 일반적으로 컴파일러는 당신을 위해 생성하는 열거가 반복되고있는 컬렉션을, 예컨대 :

public IEnumerable<Thing> GetThings() 
{ 
    yield return GetNextThing(); 
} 
+1

Unity3d 엔진은 IEnumerator를 사용하는 유일한 엔진이며, 엔진은 IEnumerable이어야합니다. 하나는 IEnumrable 이 더 좋다고 주장 할 수 있지만 Unity3d가 디자인 한 디자인과 함께해야합니다. – Sjoerd

관련 문제