Unity3D 게임 엔진의 '수율 리턴 www'의 기본 메커니즘


14

Unity3D 게임 엔진에서 원격 데이터를 가져 오는 일반적인 코드 시퀀스는 다음과 같습니다.

WWW www = new WWW("http://remote.com/data/location/with/texture.png");
yield return www;

기본 메커니즘은 무엇입니까?

다운로드가 완료되는 동안 다음 프레임을 처리 할 수 ​​있도록 yield 메커니즘을 사용한다는 것을 알고 있습니다. 그러나 우리가 할 때 후드 아래에서 무슨 일이 일어나고 yield return www있습니까?

WWW 클래스에서 어떤 메소드가 호출되고 있습니까? Unity는 스레드를 사용합니까? "상위"Unity 계층이 www 인스턴스를 잡고 무언가를하고 있습니까?

편집하다:

  • 이 질문은 특히 Unity3D 내부에 관한 것입니다. yieldC #에서 문이 작동 하는 방식에 대한 설명에는 관심이 없습니다 . 대신, 예를 들어 WWW가 여러 프레임에 분산 된 방식으로 데이터를 다운로드 할 수 있도록 Unity가 이러한 구성을 처리하는 방법에 대한 내부 관점을 찾고 있습니다.

1
사용합니다 yield return비동기 작업하는 해킹입니다. "실제"C # 프로그램에서는이를 위해을 사용합니다 Task. Unity는 .Net 4.0 이전에 만들어 졌기 때문에 Unity를 사용하지 않았을 것입니다 Task.
BlueRaja-대니 Pflughoeft

답변:


8

이것은 C # yield 키워드 로, www객체에 대해 특별한 작업을 수행하지 않고 그 안에 포함 된 메소드에 대해 특별한 의미를 IEnumerable갖 습니다. 특히이 키워드는 (또는 IEnumerator) 를 리턴하는 메소드에서만 사용할 수 있으며 사용 됩니다. MoveNext 가 호출 될 때 열거자가 "반환"할 개체를 나타냅니다 .

컴파일러는 어떤 구현하는 별도의 클래스로 전체있어서 변환 때문에 작동 IEnumerable(또는 IEnumerator상태 머신을 사용) - 최종 결과의 방법 자체의 본체는 리턴 값을 통해 누군가를 열거 할 때까지 실행되지 않는다는 점이다. 이것은 모든 유형에서 작동하며, 특별한 것은 없습니다 WWW.

한 번 봐 가지고 는 C # 수율 키워드의 장면 뒤에 정렬 C # 컴파일러가 생성하는 코드의 무엇에 좀 더 통찰력을하거나 실험과 자신이 같은 것을 사용하여 코드 검사 IL 스파이


업데이트 : 명확히하기 위해

  • Unity가 yield return명령문 이 포함 된 코 루틴을 호출 하면 열거자가 반환된다는 것뿐입니다.이 시점에서 메소드 본문이 실행되지 않습니다.
  • 메소드 본문이 Unity를 실행하게 MoveNext하려면 시퀀스의 첫 번째 값을 얻기 위해 반복자를 호출해야합니다 . 이로 인해 메소드가 첫 번째 yeild return명령문 까지 실행되어 호출자가 재개됩니다 (아마도 Unity는 나머지 프레임을 렌더링합니다)
  • 내가 이해하는 것처럼 Unity는 정상적으로 호출합니다. MoveNext 각 후속 프레임마다 반복기 메소드 메소드 yield return의 끝이나 yield break명령문에 도달 할 때까지 매 프레임마다 한 번 다음 명령문 까지 메소드를 다시 실행합니다. 순서의 끝)

유일한 특별 여기 비트 (과에서 몇 가지다른 경우는 ) 대신에서만 다운로드가 완료되면 (계속 실행 방법을 일으키는) 반복자를 진행 유니티이 특정 반복자에게 다음 프레임을 진행하지 않습니다. 기지가있는 것처럼 보이지만반복자를 향상시켜야 할 때 Unity에 신호를 보내기 위한 일반적인 메커니즘을 포함하고 YieldInstruction 클래스가있는 WWW것처럼 보이지만 클래스는이 클래스에서 상속 된 것으로 보이지 않으므로 특별한 경우가 있다고 가정 할 수 있습니다. Unity 엔진의이 클래스

명확하게 말하면- yield키워드는 WWW클래스에 특별한 작업을 수행하지 않고 Unity가 반환 된 열거 형 멤버 에게이 동작을 일으키는 특수 처리를 수행합니다.


두 번째 업데이트 :WWW 웹 페이지를 비동기 적으로 다운로드 하는 데 사용 되는 메커니즘 은 내부적으로 비동기 IO를 사용 하는 HttpWebRequest.BeginGetResponse 메소드 를 사용 하거나 스레드를 사용할 수 있습니다 (전용 스레드 작성 또는 스레드 풀 사용).


5
실제로 Unity에서는 WWW오브젝트가 생성 될 때 오브젝트에 특별한 일이 발생합니다 . WWW참조를 참조하십시오 .
Eric

9

yield코 루틴 컨텍스트에서 Unity에서 주로 사용되는 것으로 보입니다. 코 루틴 및 C #을 사용하는 이유에 대해 자세히 알아 보려면 Unity3D 코 루틴에 대한 자세한yield 블로그 기사를 참조하십시오. . 이 답변에 대한 대부분의 연구는 해당 기사에서 나옵니다.

Unity의 코 루틴은 다음과 같은 작업을 캡슐화하는 데 사용됩니다.

  1. 렌더링되는 프레임보다 오래 걸릴 수 있으므로 속도가 느려질 수 있습니다.
  2. 게임 루프와 별도로 수행 할 수 있습니다 (현재 프레임에서 결과를 사용할 수 없기 때문에).

이러한 종류의 작업의 예는 경로 찾기 (재) 계산 또는 질문과 마찬가지로 웹 사이트에서 데이터를 가져 오는 것입니다.

하위 질문에 답변하려면 (약간 수정 된 순서로) :

WWW 클래스에서 어떤 메소드가 호출되고 있습니까? "상위"Unity 계층이 www 인스턴스를 잡고 무언가를하고 있습니까?

Unity의 WWW클래스는 코 루틴에서 산출되도록 설계되었습니다. 위에 링크 된 블로그 기사에 대한 의견에 따르면 s에 대한 추론 적 코드 블록 ( ' "상위"레이어 ") YieldInstruction에는 실제로 s를 확인하는 스위치가 포함되어 있습니다 WWW. 이 코드는 WWW참조에 설명 된대로 다운로드가 완료되면 코 루틴이 자동으로 완료되도록 합니다.

Unity는 스레드를 사용합니까?

이 경우, "게임의 나머지 부분을 막지 않고"데이터를 다운로드하려면 : 그렇습니다. (스레딩은에 의해 입증 된 바와 같이 다운로드 된 데이터를 압축 해제하는 데 사용됩니다 WWW.threadPriority.)


좋은! 나는 의견 altdevblogaday.com/2011/07/07/unity3d-coroutines-in-detail/…을 보았고 WWW가 특별하게 취급되는 것 같습니다. 그래서 스레드를 사용하지 않고 여러 프레임에서 다운로드 할 수 있도록이 방법을 알고 싶습니다.
thyandrecardoso

좋은 지적! 결국 그 수준에서 몇 가지 스레딩이 진행되어야한다고 가정하고, 그것을 반영하기 위해 답변을 편집 할 것입니다.
Eric

1
@thyandrecardoso HttpWebRequest.BeginGetResponse 또는 이와 유사한 것을 사용한다고 생각 하지만 실제로 중요한 경우 어셈블리를 디 컴파일하여 확인할 수 있습니다.
저스틴

지금은 정말 "최고의 설명"만 기다리고 있습니다. Unity 개발자 팀의 누군가가 "올바른 답변"을 준 경우에는 좋을 것입니다. 8-) ... 궁극적으로 실제 구현은 그렇지 않을 것이라고 생각합니다. 여기에 이미 제공된 것들과는 거리가 멀다 ... 어셈블리를 디 컴파일하고 실제로이 모든 것을 알 필요는 없다. 그러나 나는 나중에 그것을 시도 할 수 있습니다 :)
thyandrecardoso

7

불행하게도 WWW는 내부적으로 네이티브 코드로 구현되므로 코드를 볼 수 없습니다. 실험에서 나는 말할 수 있습니다

  1. WWW은 에서 파생 되지 않으므로 특수 사례 코드로 처리해야 YieldInstruction할 때 어떤 일이 발생 yield합니다.
  2. 나는 사이에 어떤 차이를 강요하지 않았다

    yield return www;

    while(!www.isDone)
        yield return null;

    나는 그것이 그것을 구현하는 가장 논리적 인 방법이라고 생각하며, 아마도 그것이 그 밑에서 진행되고있는 것일 것 입니다. 그러나 나는 확실하지 않다.

  3. Unity는 최소한 일부 플랫폼 (iOS, 웹 플레이어)에서 다운로드를위한 새로운 스레드를 시작 하지 않습니다 . 또는 그렇다면 WWW.isDone주 스레드에 설정 됩니다. 이 코드 때문에 다음을 알고 있습니다.

    while(!www.isDone)
        Thread.Sleep(500);

    작동하지 않습니다.

Unity3d의 소스 코드에 액세스 할 수있는 사람이 여기에 오지 않으면 더 구체적인 답변을 얻을 수 있다고 생각하지 않습니다.


예. 정말 좋은 통찰력! 감사! 스레드 자체를 시작하지 않더라도 HttpWebRequest.BeginGetResponse (또는 이와 유사한 것)를 사용하는 WWW (또는 엔진 계층)가 발생할 수 있습니다. 완전히 비동기식으로 작동해야합니다. 다운로드를 "일시 중지"할 수 없습니다.
thyandrecardoso

** 프레임간에 "일시 중지"할 수 없습니다.
thyandrecardoso

2

Unity3D는 C #을 스크립팅 엔진으로 사용하기 때문에 C # 에 내장 된 표준 yield 키워드 를 가정합니다 . 기본적으로 의미하는 바는 이미 www의 값을 반환하여 다음 반복 동안 다음 값을 반환하는 동안 계속할 수 있다는 것입니다. Yield는 기본적으로 백그라운드에서 상태 머신과 반복자를 만듭니다.


예, 수익률 키워드에 대한 기본 개념이 있다고 생각합니다. 그러나 WWW 생성자 중에 "상태 머신"을 허용하는 상황은 무엇입니까? 내 말은 "수익률 www 반환"이 WWW 클래스 내부에서 아무 것도 호출하지 않는 것 같습니다 ... "이미 www 값을 이미 반환한다는 의미"라고 말하면 www 인스턴스 값은 무엇입니까? 다음 "반복"에서 해당 인스턴스는 무엇을합니까?
thyandrecardoso

1
Unity 코 루틴에서 WWW 생성은 특별한 경우입니다 (참고 WWW자료 참조) . 또한 확실하지 않습니다 yield. 반복자 컨텍스트는이를 구현 IEnumerable하거나 리턴 유형으로 사용하여 작성됩니다 . "상태 머신"도 꺼져 있습니다. 물론, 국가가 있지만 그 자체만으로는 충분한 재산이 아닙니다. 아마도 당신은 그것에 대해 자세히 설명 할 수 있습니다.
Eric

1
다음은 일반적인 C # 동작에 대한 좋은 참조입니다. shadowcoding.blogspot.nl/2009/01/yield-and-c-state-machine.html . Yield는 반복자의 위치를 ​​추적하기 위해 많은 코드를 생성합니다. WWW를 생성하는 Unity의 특수 사례에 대해서는 알지 못했지만 문서에 따르면 일반적인 C # 키워드와 관련이 없으며 매우 혼란 스럽기 때문에 비동기 방식으로 만들 수 있습니다.
Roy T.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.