No special preview this week I’m afraid, but there is a game update.

I didn’t intend to do an update right at this moment but I’ve finally, finally fixed a memory leak on the Scraps server that I’ve been trying to track down for months. I’ve been looking at it on and off in the evenings so that it didn’t impact development on the game, but I’ve also really wanted to get it fixed. If you ran a game, even a single-player one, for a long time with lots of vehicles being spawned and destroyed, it’d eventually mess up and weird things would start to happen – like all damage would stop registering. It also meant that dedicated servers needed much closer supervision than they should have needed.

In the meantime while I’ve been working on the new game mode I’ve also been fixing other things, so there are some other bonus changes here as well.

Changelog

2016-6 – 0.5.4.4

– Added partial Polish translation

– Adjusted collision damage down a little

– Adjusted AI targeting a little. More shots at parts, less direct chassis shots

– AI aiming calculation now takes the shooter’s velocity into account as well as the target’s. Be afraid

– Made the in-game chassis colliders more detailed. Previously there was a box that could end up “protecting” some low components like small engines, with the chassis taking damage instead of the hit part

– Adjusted some sounds and volumes of various things

– Removed wreckage size scaling as it spawned since it looked dumb and was dumb

– Had to exclude screen resolutions that don’t match your monitor’s aspect ratio due to a bug in the Unity engine. On Linux resolution reporting is too fickle to limit: If a chosen res doesn’t look right, just try another one

– Added visual indicator to health bars to help show when damage is done

– Wreckage pickup is far more performance-efficient. No more slowdown when complex vehicles drive over wreckage.

Bug Fixes:

– FINALLY tracked down a memory leak on the server that was causing trouble when running the game for a long time

– Fixed a couple of bugs with bullet spread. Machine-guns were more accurate than they looked visually (they match the visuals now)

– Projectile trail FX angle fix

2016-4 – 0.5.4.3

– Improved AI pathing quite a bit

– If AI gets stuck persuing in a circle, it’ll eventually break out

– Updated the vehicle/environment shader look a little

Bug Fixes:

– ATI cards that didn’t support DirectX 11 had some issues with the new terrain shader. Disabled some features if ATI+DX9 is detected to help the look

Info on the bug in the form of a technical description

The Scraps server was slowly using up more and more RAM, until eventually the whole thing would crash with a stack overflow exception. But the stack wasn’t the problem – it was the heap.

I knew that it was the heap because looking at the Unity profiler, it appeared that all objects were being garbage collected just as they should be, but the thing that grew was Other->ManagedHeap.UsedSize. In other words things on the heap were getting allocated and not deallocated, so the heap had to keep growing when new things were made.

Unfortunately in Unity it’s impossible to inspect the heap, although it is now possible on platforms that use IL2CPP. Being able to inspect the contents of the heap would have solved this much faster.

I fairly quickly worked out that creating and destroying vehicles was the problem, but the profiler reported that everything on the vehicles was successfully destroyed. Yet the leak implied something big was being held onto. There had to be a reference somewhere to something on a vehicle from something outside of the vehicle, that never got freed.

My eventual discovery after slowly hacking pieces of Scraps apart was that it was an event subscription to an event on a static class.

Scraps parts have a Health class that’s a MonoBehaviour, and Health has a non-MonoBehaviour class that acts as a sub-component to do different things depending on whether this is a client or server machine (remember that this leak only happened on the server).

When the health script was created, the member class subscribed to a static tick event on a static clock class that the server has. When the health script was destroyed, it run its explosion effects and all that, and also told the member class to unsubscribe from its event… most of the time.

The problem was that the Health script’s call to the member class wasn’t in its OnDestroy, it was in another method that did all the destroying actions for the part and then called Destroy() itself – and that method didn’t get called in every situation. Thus sometimes the event never got unsubscribed, and the reference to the member class was held by the static clock class forever, preventing it from being destroyed.

Much more was being retained on the heap than just that one class, so my theory is that Unity was managing to remove the vehicle’s data on the C# side, but not in the C++ back-end. Thus the profiler would show that every object was destroyed successfully, but in fact the static clock class’ reference held onto the non-MonoBehaviour class which in turn was holding onto the whole vehicle part with its memory-consuming mesh and textures.

To fix the issue for certain I basically just moved the cleanup code into the OnDestroy of the Health script, guaranteeing that if the script is destroyed, its member class gets cleaned up as well.

TL;DR: If your heap is growing forever and you aren’t leaking any objects, one thing to look for is events that mightn’t be being unsubscribed. And don’t think that a GameObject being gone means it’s necessarily really gone.

Info on the bug in the form of a story

Guests come to a party at your place and they want to use your dinnerware, but you want to keep track of who’s taken some out of the cupboard so when a guest takes a plate, you also get them to tie a rope around their wrist with the other end tied to the cupboard (you’re a particularly annoying host).

When a guest leaves the party, they’ll put back their plate, untie their rope, and leave.

But sometimes, due to an oversight in your party planning, guests can leave without returning their plate – with their rope still tied to the cupboard!

Later the party is over and it looks like everyone’s left, but you find that you can’t fully close the door because there are some ropes still tied on to a bunch of people outside. Over time and several parties, you accumulate more and more guests who are still tied on with ropes.

You find that you cannot get all guests to return their plates before they leave (as a terrible host I assume you’ve also attracted terrible quests). But you can fix the problem. You revise your party rules so that instead of guests untying their ropes when they return their plate, they must untie their rope when they leave the party, no matter what. Now your house and yard are properly cleared out every time a party is over. And you buy some new plates I guess.