Best practise to switch between coroutine and synchronous execution?

I am instantiating objects in the background using coroutines. For example, user starts at the first section of a level, and as they play through, I instantiate objects that are used later. I use coroutines to spread out the instantiation of many objects over many frames in order to avoid long frames and therefore cpu spikes/framerate drops.

However, I would also like to be able to drop a user directly into a later part of a level, so I want to instantiate all the required objects immediately. Rather than using the same coroutine method, I want to do it all in one synchronous, blocking call. Using coroutines takes longer, but there is no need to hide the instantiation in the background because it is now happenning on level load, probably behind a loading screen or something.

My loading/instantiation functions that are coroutine-based are sprinkled with yield calls, and called with StartCoroutine(). I thought I could wrap all yield calls with another function that first checks if(useCoroutine) or something. But I’m wondering if someone else has encountered this before and has some other solution.

What are best practices for switching between executing a function with a coroutine or with a synchronous blocking call?

EDIT


Another idea:

void Start(){
	If("we are far away"){
		StartCoroutine(CoroutineController(false); //run with yields
	}else{
		StartCoroutine(CoroutineController(true)); //run without yields
	}
}


IEnumerator CoroutineController(boolean Force){
	IEnumerator[] CoroutinesToExecute = new IEnumerator[2] {First(), Second()};

	for(int i = 0; i < CoroutinesToExecute.Length; i++){
		while(CoroutinesToExecute*.MoveNext()){*

_ if(!Force) yield return CoroutinesToExecute*.Current;_
_
}_
_
}*_

}

IEnumerator First(){
* //blah*
* yield StartCorountine(Third());*
}

IEnumerator Second(){
* //blah*
}

IEnumerator Third(){
* //blah*
}
I know this works normally, though I am unaware how this behaves for the nested coroutines, I can’t test right now, but would be very interested if it works.
----------
Original
--------
----------
Sometimes I do this, though I’m not certain it is the best technique:
GameObject[] someArrayOfObjects;

void Start(){
* If(“we are far away”){*
* StartCoroutine(YourCoroutine(someArrayOfObjects, 1)); //build one at a time*
* }else{*
* StartCoroutine(YourCoroutine(someArrayOfObjects, someArrayOfObjects.Length)); //build them all at the same time*
* }*

}

IEnumerator YourCoroutine(GameObject[] objArray, int ToForce){
* int count = 1;*
* for(int i = 0; i < objArray.Length; i++){*

_ ForceSomething(objArray*);*_

* if(count == ToForce){*
* count = 0;*
* yield return null;*
* }*

* count ++;*
* }*
}

void ForceSomething(GameObject go){
* //your single instantiation perhaps*
* Instantiate(go);*
}
Hope it helps!
Scribe

Coroutines must be of type IEnumerator. For nested coroutines, Unity automagically handles the case where yield returns another Coroutine. So I simply wrap StartCoroutine() with another function that calls StartRoutine() if running async, or manually iterates with MoveNext() if not. I can now write all my init functions as IEnumerators, and call them with the wrapper function.

public static Coroutine StartFunc(IEnumerator func, bool async = false)
{
	if(async)
	{
		return SomeGameObject.Instance.StartCoroutine(func);
	}
	else
	{
		while(func.MoveNext());
		return null;
	}
}

...
usage:

StartFunc(DoInit(), async);

or a nested call:

yield return StartFunc(DoSomethingElse(), async);