Fire bug crashing game causing bad lag and insane amounts of errors a second

Started by shmooe, October 07, 2014, 08:59:21 PM

Previous topic - Next topic

VStraken

I've gotten this problem on one of my latest games, and it's only about 3/4 of the way into the 2nd year that it's happened; last time it happened rather late into the 3rd year. I've also tried the workaround posted, but to no avail.

MyNameIsChaz

I've had the same problem. It started around year 2-3 and would severely lag the game. I played through it however, and eventually it just stopped happening (around year 6-7) and my fire is back to normal. I play with only one mod- Prepare Carefully.

SmallEquine

Can confirm that the fire bug happens every time it gets to year 3. Its a shame because thats around the time my colony gets big but i cant play it because the fps drop every time there's a mechtoid raid. i really hope there's a fix.

qwe85


Tynan

thanks greatly for the info everyone.

This bug has been hard to find but with the savegames and year-3 reports I may be able to solve it.

https://ludeon.com/mantis/view.php?id=1648
Tynan Sylvester - @TynanSylvester - Tynan's Blog

qwe85

Hi,

I have found a way to reproduce it.
There is a slow and a quick way.

Slow.
1. Create new world
2. Create new colony on the new world
3. Start alot of fires
4. Time accelerate until almost everything is burned down.
5. Save Colony
6. Repeat step 2-5 until the error occur

Quick.
1. Create new world
2. Edit new world setting nextThingId to 5420000 (Remember to save)
3. Create new colony on the new world
4. Start modest amount of fires
5. Time accelerate until the error occur.

It seems the magic number is 5.492.076.
When a fire with Id 5492076 or higher starts the error occurs


/ qwe85

skullywag

Tynan what exactly is all the math for at the top of the drawworker in graphic_flicker. Its using thingIDs and based on the above comment it sounds very plausible Its in the right area.
Skullywag modded to death.
I'd never met an iterator I liked....until Zhentar saved me.
Why Unity5, WHY do you forsake me?

Tynan

Quote from: qwe85 on March 30, 2015, 05:18:48 AM
Hi,

I have found a way to reproduce it.
There is a slow and a quick way.

Slow.
1. Create new world
2. Create new colony on the new world
3. Start alot of fires
4. Time accelerate until almost everything is burned down.
5. Save Colony
6. Repeat step 2-5 until the error occur

Quick.
1. Create new world
2. Edit new world setting nextThingId to 5420000 (Remember to save)
3. Create new colony on the new world
4. Start modest amount of fires
5. Time accelerate until the error occur.

It seems the magic number is 5.492.076.
When a fire with Id 5492076 or higher starts the error occurs


/ qwe85

That's amazing!

Thank you!
Tynan Sylvester - @TynanSylvester - Tynan's Blog

Tynan

Yes it makes perfect sense now. The problem is in here.

int adjustedTickCount = Find.TickManager.TicksGame;
int tickIndex = 0;
int frameIndex = 0;
Fire fire = null;
float fireSize = 1;
if( thing != null )
{
adjustedTickCount += thing.thingIDNumber*391; //Offset

tickIndex = adjustedTickCount / BaseTicksPerFrameChange;

//Determine frame graphic from indices in random order
//I wish I could make this never repeat frames
frameIndex = (tickIndex ^ (thing.thingIDNumber*391)) % subGraphics.Length;

fire = thing as Fire;
if( fire != null )
fireSize = fire.fireSize;
}

Graphic frameGraphic = subGraphics[frameIndex];


//Determine draw scale
float drawSize = Mathf.Min(fireSize / 1.2f, 1.2f);

//Determine draw pos
//Choose a random offset by selecting a random square from the radial pattern
Vector3 curOffset = GenRadial.RadialPattern[tickIndex % GenRadial.RadialPattern.Length].ToVector3() / GenRadial.MaxRadialPatternRadius;
curOffset *= MaxOffset;
Vector3 drawPos = loc + (curOffset * fireSize);

//Draw
Vector3 scaler = new Vector3( drawSize, 1, drawSize);
Matrix4x4 matrix = new Matrix4x4();
matrix.SetTRS( drawPos, Quaternion.identity, scaler);

Graphics.DrawMesh(MeshPool.plane10, matrix, frameGraphic.MatSingle, 0);



This code chooses a frame for the fire to draw functionally. As in it doesn't use any stored state, it just determines which animation frame to draw based on the current tick and the id of the fire.

The problem is this: adjustedTickCount += thing.thingIDNumber*391; //Offset

It turns out that multiplying by 391 is a bit of a problem. Because the numbers can get so big that they go out of the integer range!

The failure id (5492076) times 391 is 2147401716. Which is very close to a familiar number: the max value of a signed 32-bit integer is 2,147,483,647.

Oddly this is the first time I've run into an integer wrapping error. I'm sure it won't be the last. Thanks again qwe.
Tynan Sylvester - @TynanSylvester - Tynan's Blog

Tynan

Tynan Sylvester - @TynanSylvester - Tynan's Blog