Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

Absolute Power Corrupts Minus the Power

Author: Jonah McConnell

As the infamous saying goes, absolute power corrupts absolutely. As it turns out... so do bad pointers. You may wonder why I bring this up, or you may have dealt with hanging pointers yourself and know my pain firsthand. In an engine like Unreal, however, such a common mistake meant a myriad of other issues presented themselves without revealing the underlying issue at play. The majority of my week lay in stepping through our code to deduce where the issue occurred. It wasn't until I remembered an issue I had run into in the past during our Game Development IV class. There we were tasked with making a custom engine and renderer from scratch to support a small demo game in a month. The defining issue of the project easily was creating and destroying instances of models.


In the scope of the renderer I was writing, this was an issue because the rest of the engine referenced the Transforms via a pointer to their location in a collection in the renderer. For some, this phrase alone is already setting off red flags. For context, collections can potentially change where their underlying data is in memory, leaving pointers hanging. These pointers think they point to an object when in reality the block of memory is no longer valid. In that scenario the issue was aggravated further by other constraints involving sending data to the GPU, however, this project luckily shared none of these constraints.


For this project, rather than have to find a complicated solution, we luckily had the luxury of switching to a collection of pointers to sidestep the issue... that is, once a slightly less complicated solution was engineered. Unlike the previous example in which we were bound by sending blocks of memory to the GPU, in Planetarium our issue was serialization. In our past builds we simply serialized the whole struct at once, allowing Unreal to automatically handle the wrapper information for the collection, and call the serialization function for each object in the collection. However, when switching to pointers we lost this ability. For reasons I was unable to deduce, the automatically created function to serialize a UObject pointer was crashing every time it was called, and I could not find a way to override it.


This led to the final solution seen above. In this implementation, I had to serialize data to help reconstruct the maps on deserialization.  This is because to serialize the data I had to dereference the pointer, which means the pointer must be a valid memory address. This isn't even much of a consideration when serializing the data, however when attempting to deserialize the data, the collections are empty and thus there are no valid addresses. This is crucial since the same function is called both when serializing and deserializing. This posed an interesting design challenge in that I had to find a programmatic way to determine when the code was running. In the solution above I do this by comparing the cached value of the length of the array of keys to each map. This is identical after serializing the data, however, when it has just deserialized the data, the two will not match, allowing me to prep the collections to deserialize the data.

This concluded the lengthy set of changes I spent the vast majority of my work on this week. However, compared to previous weeks, this solution felt much more fulfilling to reach. Rather than missing a single detail, or some small mistake somewhere, I had to architect a solution that was not only efficient as I usually strive for, but one that would solve the convoluted problem before me. Due to the nature of the resolution, despite being proportionally more egregious than many of my other tasks in terms of overage on my hours, I don't feel as poorly about spending the time I did on this task. Past weeks felt like I had not only underestimated the time for the task and simply wasted time spinning my wheels. This week on the other hand felt as though I underestimated the depth of the change I was attempting to make, but handled each new design problem in stride,  slowly working towards the solution of what ended up being a more difficult issue than expected. This made me feel proud of what I accomplished in this week, which is something I've missed for many weeks recently.

Support this post

Did you like this post? Tell us

Leave a comment

Log in with your itch.io account to leave a comment.