Wednesday, February 5, 2020

unity - The underlying mechanism in 'yield return www' of Unity3D Game Engine


In the Unity3D game engine, a common code sequence for getting remote data is this:


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

What is the underlying mechanism here?



I know we use the yield mechanism in order to allow the next frame to be processed, while the download is being completed. But what is going on under the hood when we do the yield return www ?


What method is being called (if any, on the WWW class)? Is Unity using threads? Is the "upper" Unity layer getting hold of www instance and doing something?


EDIT:



  • This question is specifically about Unity3D internals. I'm not interested in explanations of how yield statement works in C#. Instead, I'm looking for an inside view of how Unity deals with these constructions, to allow, for example, to WWW to download a piece of data in a distributed manner across several frames.



Answer



This is the C# yield keyword in action - its not doing anything special with the www object, rather its means something special for the method its contained in. Specifically this keyword can only be used in a method which returns an IEnumerable (or IEnumerator), and is used to indicate what object will be "returned" by the enumerator when MoveNext is called.


It works because the compiler converts the entire method into a separate class which implements IEnumerable (or IEnumerator) using a state machine - the net result is that the body of the method itself is not executed until someone enumerates through return value. This will work with any type, there is absolutely nothing special about WWW, rather its the containing method which is special.


Take a look at Behind the scenes of the C# yield keyword for some more insight into what sort of code the C# compiler generates, or just experiment and inspect the code yourself using something like IL Spy





Update: To clarify



  • When Unity calls a coroutine that contains a yield return statement all that happens is that an enumerator is returned - none of the method body is executed at this point

  • To get the method body to execute Unity must call MoveNext on the iterator in order to get the first value in the sequence. This causes the method to execute up to the first yeild return statement, at which point the caller resumes (and presumably Unity goes on to render the rest of the frame)

  • As I understand it Unity normally then goes on to call the MoveNext method on the iterator once each subsequent frame, causing the method to execute again up to the next yield return statement once each frame, until either the end of the method or a yield break statement is reached (indicating the end of the sequence)


The only special bit here (and in a couple of other cases) is that Unity doesn't advance this particular iterator the next frame, instead it only advances the iterator (causing the method to continue executing) when the download has completed. Although there does appear to be a base YieldInstruction class which presumably contains a generic mechanism for signalling to Unity when an iterator should be advanced, the WWW class doesn't appear to inherit from this class so I can only assume that there is a special case for this class in the Unity engine.


Just to be clear - the yield keyword doesn't do anything special to the WWW class, rather its the special handling that Unity gives to the members of the returned enumeration which causes this behaviour.





Update the second: As for the mechanism that WWW uses to download web pages asynchronously it probably uses either the HttpWebRequest.BeginGetResponse Method which will internally use asynchronous IO or alternatively it could use threads (either creating a dedicated thread or by using a thread pool).


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...