Hi folks, I’m trying to figure out how to spread loops over large sets over time so they don’t suck up too many fps. Here’s what I’ve come up with.
Is there a known better way or any other comments on how to approach this problem?
Anyone have a better way to handle pauses? Perhaps allow completion of the coroutin on pause and then restart on unpause? The current method works and when paused I see a huge increase in FPS, which is good.
IEnumerator LoadBalancedLoop() {
float breakTime;
int i = 0;
int length = 2000000; //would be Array.Length-1;
float maxTimePerStep = 1/1200f;
while (true) {
//isSimPaused is my own pause bool, means calculations not needed
while (!isSimPaused Time.realtimeSinceStartup < breakTime) {
if (i % 100000 == 0) {
//Debug.Log is slow enough to alter results, so turn off except for debugging
Debug.Log(i+" indexed at RealTime:"+Time.realtimeSinceStartup);
}
i++;
if (i > length) {
//reached end of array. Reset and get out
//or could start over and not break
i = 0;
break;
}
//would operate on array[i] here
}
yield return null;
}
yield return null;
}
It’s better just to use threads.
–Eric
Oh, that would be nice. I thought unity was not thread-able though. I should mention I am using things like Raycast inside the loop.
Yeah, Raycast wouldn’t work since the Unity API is not thread-safe. You can use any thread-safe Mono functions in threads though.
–Eric
As I thought, thanks. It’s possible I could get rid of the Raycasting dependency in this case, but meanwhile…
I just tried implementing my concept in a fairly complex loop (testing Line-of-sight for each and every Entity in the scene). This has loops inside loops and is hard to deconstruct as I had it above. I came up with a less pretty but easier to use method.
Again, anyone run into trouble doing it this way?
public IEnumerator LoadBalancedUpdateView ()
{
float maxTimePerStep = 1 / 1200f;
float breakTime = Time.realtimeSinceStartup + maxTimePerStep;
bool didYield = false;
while (true) {
if (LevelManager.isSimPaused) {
yield return new WaitForSeconds(1);
}
if (LevelManager.isSimPaused) {
// this looks weird but takes advantage of the fact that the
// loop picks up here after the yield, so we 'do not pass go' and
// go back to top and check against isSimPaused
continue;
}
//some loops within loops here and at a likely spot I put in this.
//in fact I think these could be sprinkled through the loops just after likely bottle-necks
foreach (thing in these) {
foreach(foo in bar) {
if (Time.realtimeSinceStartup > breakTime) {
didYield = true;
yield return null;
}
if (didYield) {
//picking up again after a yield
//reset the time we should return from;
breakTime = Time.realtimeSinceStartup + maxTimePerStep;
didYield = false;
}