My Player.log is full of the message “Car hasn’t been updated in 200 simulation frames. Destroying.” So I investigated.
Cars have a watchdog mechanism that destroys them if nobody is feeling responsible for them anymore. Normally, the lane they are on or the train or station they are currently in has the responsibility over these cars. So normally they would always update them and everything would be fine, but still some places in my settlement were notorious for eating cars every now and then.
The reason is this code segment at the beginning of LaneBase
’s UpdateSimulationThread()
:
if ((Old.GetSimulator().simulationFrame + GetID()) % 50 == 0L)
{
incomingCar?.UpdateWatchdog();
outgoingCar?.UpdateWatchdog();
for (int i = 0; i < carsNew.Count; i++)
{
carsNew[i].first.UpdateWatchdog();
}
}
The watchdog for cars on lanes is only updated every 50 frames. Now normally this wouldn’t be a problem with a 200 frames tolerance window for the watchdog, but the problem happens when cars switch lanes quite fast, as can happen especially around intersections. And an intersection is any place where at least 2 roads meet (the blue circles in building mode). A car may leave one lane shortly before that lane would have called UpdateWatchdog()
. Then the new lane is responsible for triggering the watchdog update. But since the new lane has a different ID, the next watchdog update may take up to 50 frames to occur. And this is actually enough time for the car to leave that lane and enter a new one, without receiving any update to its watchdog. If this happens several times in a row, then the 200 frames can be exceeded even though the car was on proper lanes all the time and was indeed updated, but the watchdog update just never happened. Since this depends on the specific IDs of the lanes in sequence, the watchdog exceeding happens in the same spots on the map where the ID offsets align in an unfavorable way with the speed of the cars traveling through those nodes. Also, the nodes need to be close and the faster the cars can move (think: highways or super highways) the more likely. If you want to reproduce this, simply build this and watch it eat cars pretty frequently:
The fix is simple: Make sure that the watchdog is also updated whenever a car switches lanes. For me the easiest way to test if this would solve the problem was to patch LaneBase.RemoveOutgoingCar()
so it would update the watchdog. The new method would need to look like this:
public Car RemoveOutgoingCar()
{
if (HasOutgoingCar())
{
outgoingCar.UpdateWatchdog();
Car result = outgoingCar;
outgoingCar = null;
return result;
}
return null;
}
Now with this patch I still get cars being destroyed, especially after loading, but these cars are at position (0.00, 0.00, 0.00). So they have some other problems I still need to investigate. But it’s a different cause.
As an afterword, the watchdog is only a debugging tool anyway. In an InfraSpace that works smoothly, this feature is actually not necessary. But for now it’s useful to find bugs, but unfortunately this debugging tool has a bug itself that causes cars to be destroyed occasionally and seemingly (but not quite!) randomly.