I’ve got the following code snippet, and the Unity profiler is saying that Tile.UpdateWater() is generating about 0.6mb of GC Alloc per frame (it’s called 131,000 times per frame). But it does not instantiate any arrays or classes, and it does not use strings at all.
I’ve tried removing chunks of code, but I couldn’t track it down through that method either because it would allocate fully one run, but allocate nothing the next run on the same code at times. It’s really driving me up a wall.
I’ve also tried pulling this function out into it’s own static class with all local variables predefined as static class variables, but that only seemed to make it worse.
The only local variables being defined are ints and floats, but those shouldn’t trigger allocations, right?
public class Tile
{
public enum Modes
{
Nothing,
FloorOnly,
FloorWall,
FloorStairs,
FloorRamp,
WallOnly,
StairsOnly,
}
private float WaterAmt;
private Tile North, South, East, West, Below, Above;
public Modes Mode;
public bool HasWall()
{
return Mode == Modes.WallOnly || Mode == Modes.FloorWall;
}
public void UpdateWater()
{
if (WaterAmt > 1)
WaterAmt = 1;
if (WaterAmt <= 0)
return;
if (HasWall())
{
WaterAmt = 0;
return;
}
float maxFlowAmt = Mathf.Min(0.5f, Time.deltaTime * 5);
if(Mode == Modes.Nothing && Below != null)
{
if (!Below.HasWall())
{
float toDrop = Mathf.Min(1 - Below.WaterAmt, WaterAmt);
Below.WaterAmt += toDrop;
WaterAmt -= toDrop;
}
}
if (WaterAmt <= 0)
return;
int ct = 1;
float totalWater = WaterAmt;
if (West != null && !West.HasWall())
{
ct++;
totalWater += West.WaterAmt;
}
if (East != null && !East.HasWall())
{
ct++;
totalWater += East.WaterAmt;
}
if (South != null && !South.HasWall())
{
ct++;
totalWater += South.WaterAmt;
}
if (North != null && !North.HasWall())
{
ct++;
totalWater += North.WaterAmt;
}
float avgWater = totalWater / ct;
if (ct <= 1)
return;
if (avgWater >= 0.9999999f)
return;
if (avgWater < WaterAmt)
{
float needW = 0, needE = 0, needN = 0, needS = 0;
if (West != null && !West.HasWall())
needW = Mathf.Max(avgWater - West.WaterAmt);
if (East != null && !East.HasWall())
needE = Mathf.Max(avgWater - East.WaterAmt);
if (South != null && !South.HasWall())
needS = Mathf.Max(avgWater - South.WaterAmt);
if (North != null && !North.HasWall())
needN = Mathf.Max(avgWater - North.WaterAmt);
float totalNeed = needW + needE + needN + needS;
if (totalNeed > 0)
{
float maxToGive = WaterAmt - avgWater;
if (totalNeed > maxToGive)
{
needW *= (maxToGive / totalNeed);
needE *= (maxToGive / totalNeed);
needN *= (maxToGive / totalNeed);
needS *= (maxToGive / totalNeed);
}
if (needW > 0)
{
float amt = needW * maxFlowAmt;
West.WaterAmt += amt;
WaterAmt -= amt;
}
if (needE > 0)
{
float amt = needE * maxFlowAmt;
East.WaterAmt += amt;
WaterAmt -= amt;
}
if (needN > 0)
{
float amt = needN * maxFlowAmt;
North.WaterAmt += amt;
WaterAmt -= amt;
}
if (needS > 0)
{
float amt = needS * maxFlowAmt;
South.WaterAmt += amt;
WaterAmt -= amt;
}
}
}
}
}