In Unity, say you have a GameObject
. So, it could be Lara Croft, Mario, an angered bird, a particular cube, a particular tree, or whatever.
(Recall that Unity is not OO, it's ECS. The Component
s themselves which you can "attach" to a GameObject
may or may not be created in an OO language, but Unity itself is just a list of GameObject
s and a frame engine that runs any Component
s on them each frame. Thus indeed Unity is of course "utterly" single-thread, there's not even a conceptual way to do anything relating to "actual Unity" (the "list of game objects") on another1 thread.)
So say on the cube we have a Component
called Test
public class Test: MonoBehaviour {
It does have an Update pseudofunction, so Unity knows we want to run something each frame.
private void Update() { // this is Test's Update call
Debug.Log(ManagedThreadId); // definitely 101
if (something) DoSomethingThisParticularFrame();
}
Let's say the unity thread is "101".
So that Update (and indeed any Update of any frame on any game object) will print 101.
So from time to time, perhaps every few seconds for some reason, we choose to run DoSomethingThisFrame
.
Thus, every frame (obviously, on "the" Unity thread ... there is / can only be one thread) Unity runs all the Update calls on the various game objects.
So on one particular frame (let's say the 24th frame of the 819th second of game play) let's say it does run DoSomethingThisParticularFrame
for us.
void DoSomethingThisParticularFrame() {
Debug.Log(ManagedThreadId); // 101 I think
TrickyBusiness();
}
I assume that will also print 101.
async void TrickyBusiness() {
Debug.Log("A.. " + ManagedThreadId); // 101 I think
var aTask = Task.Run(()=>BigCalculation());
Debug.Log("B.. " + ManagedThreadId); // 101 I think
await aTask;
Debug.Log("C.. " + ManagedThreadId); // In Unity a mystery??
ExplodeTank();
}
void BigCalculation() {
Debug.Log("X.. " + ManagedThreadId); // say, 999
for (i = 1 to a billion) add
}
OK so
I'm pretty sure at A it will print 101. I think.
I guess that at B it will print 101
I believe, but I'm uncertain, at X it will have started another thread for BigCalculation. (Say, 999.) (But maybe that's wrong, who knows.)
My question, what happens, in Unity, at "C" ?
What thread are we on at C, where it (tries to?) explode a tank????
I believe in normal .Net environments, you'd be on another thread at C, say 202.
(For example, consider this excellent answer and notice the first example output "Thread After Await: 12". 12 is different from 29.)
But that's meaningless in Unity -
... how can TrickyBusiness
be on "another thread" - what would that mean, that the whole scene is duplicated, or?
Or is it the case that (in Unity especially and only? IDK),
at the point where TrickyBusiness
begins, Unity actually puts that (what - a naked instance of the class "Test" ??) on another thread?
In Unity when you use await
what does it print at C, or A for that matter?
It would seem that:
If indeed "C" is on a different thread - you simply can't use awaits in that way in Unity, it would be meaningless.
1 Obviously some ancillary calculations (eg, rendering, whatever) are done on other cores, but the actual "frame based game engine" is one pure thread. (It's impossible to "access" the main engine frame thread in any way whatsoever: when you are programming, say, a native plugin or some calculation which runs on another thread, all you can do is leave markers and values for the components on the engine frame thread to look at and use when they run each frame.)