CoderMonk, thanks for this, that’s helped me dig a little deeper.
I’ve realised where I was getting confused. The yield statement is a c# .net implementation and the coroutine is a unity implementation and I was trying to determine the behaviour of the yield return without understand what the coroutine statement was doing.
This is my current reasoning.
Unity refers to the coroutine as a way in which to execute an Enumerated method in a single frame update. The single frame is the important part of this because the yield return is the way the coroutine is signalled to move onto the next frame and continue execution where the loop left off (after the yield statement) until the loop completes then the coroutine releases control.
If the yield returned null the coroutine would still work (but probably pointless) as it would just make the coroutine move to the next frame on every frame.
In our game code we are returning a new object of type WaitForSeconds instead of using null to make the yield return delay its return to the coroutine so we can manage enemy spawning speed.
Moving onto the EnemyPathing instantiation start() method.
I cant find where it is actually documented, but based on what you have shared I think what is happening is the EnemyPathing start() method wont execute until the yield statement has performed a return. That will signal the coroutine to move to next frame and that is when unity gets the EnemyPathing script to execute its start() method. The delay from instantiation to start () being invoked allows us a window to script any pre-configuration settings the object needs to work.
Which is why if I were to change the order (as below), the EnemyPathing start() would report a reference error.
yield return new WaitForSeconds (waveConfig.GetTimeBetweenSpawns());
newEnemy.GetComponent().SetWaveConfig(waveConfig);