Postmortem & Bug Fix: Fireworks


This is the first in a series of postmortems where I will be evaluating my previous projects. Fireworks is the first project I completed as a solo developer in Unity, and was completed as a part of a game jam in 2018.

About the project

Fireworks is a touch-typing game that displays four characters from the English alphabet with each character connected to a firework that moves from the bottom of the screen to the top. When a generated character key is pressed by the user, the corresponding firework will burst. In the event that the letter key is not pressed before the firework goes off screen, the firework should be transported back to underneath the screen view, and assigned a new character.

Fireworks: In-game screenshot showing A,B,C,D as the generated keys, with the corresponding fireworks visible.

During this postmortem, I hope to resolve the issue described by @irdumb here

I did notice that after I tried to make all 4 fireworks explode at once in one action, now only 3 letters show up and the 4th firework can never be sploded.

The situation as I understand it is that somehow the relationship between the firework asset and the corresponding text component has been broken. Fortunately the architecture of this project is relatively simple, contained in only a few scripts, which are relatively decoupled in terms of functionality. 

Replicating the issue

In the screenshot @irdumb provided in their comment, it was evident that Fireworks was being run at a relatively high resolution, so in trying to replicate the issue, I decided to start there. I  varied the activation of firework explosions at various points along the vertical axis in screen space, eventually experiencing the bug. Following the same process, I managed to replicate it once again in the editor, matching the resolution I selected in the game build. As the possible problem space was quite narrow, I did not sense a need to develop any other tests at this time.

From the properties visible in the Inspector it was evident that the offending Firework prefab was marked as 'isBursting'  the state where the Firework has exploded, producing a visual effect prior to being reset to the birth position below the screen view, despite that not being the case. The scripts that manage the text boxes are designed to update with a new key only if the Firework object is designated as not bursting. A link to that specific block of code can be found here on Github.

Analysing the code

The code for handling the transition states for the firework objects is in an aptly named file called Firework.cs which you can find here, on Github, should you be interested. Otherwise, you may peruse the pseudo-code for the Update() function is below.

// UPDATE() 
 if ( rocket state is active AND corresponding key is pressed ) {
   label status as is bursting
   toggle burst
   toggle rocket
   play explosion sound
 }
 
if (burst particle state is active AND the burst particle effect has completed ) {
   label status as not bursting
   toggle burst
   toggle rocket
   RESET() function call
 }
if (off screen in the positive y-direction) {
   RESET() function call
 }

The pseudo-code may seem sensible enough. The code for Reset is hosted on Github here. The pseudo-code for the Reset method is below.

// RESET() 
turn off the rocket particle system (whether it is on or off)
set the velocity of the overall gameObject to zero
put the overall gameObject in its initial position
turn on the rocket particle system
launch the firework upward into screen-space

From here the reader might be able to piece together that the issue is being caused by emergent behaviour from a sequence of events. 

Identifying the root cause

If a firework is bursting as it is moving off-screen it will not be forcibly turned off by Reset(), it will be allowed to finish. This means that the rocket and burst component will both be active at the same time. If the user manages to press the next key during this window, the first block of code inside the Update method will be executed in the next frame, which will set both the rocket and bursting components to an off-state before eventually resetting to its initial position due to the object moving upward off-screen. At this point, the rocket will be re-enabled, but at no point during this sequence of events was the isBursting status variable set to false. As a consequence, the textbox is left blank. Keys are still being generated and if the user happens to press the key mapped to the stray firework, everything old will be new again (effective hard reset of the firework object). This can occur by accident (pressing the corresponding key with no prompt) or by chance due to another firework being mapped to the same key. In this case, a single key press would set off both fireworks.

Resolving the design issue

The current situation is that a firework currently continues moving upward into screen-space (and eventually is moved to its initial position by a block inside Update) but there is no reason this needs to be the case. One option could be to add a margin, in pixels where the firework is allowed to travel before resetting its position, however this approach does not scale to multiple resolutions very well. A better solution would be to copy the existing line in Reset that sets the velocity of the rigidbody to zero, and execute it inside the code block that triggers the burst. As a redundancy measure, the status of isBursting has been set to false inside the Reset method.

We're all done! Thanks for reading.

Get Fireworks: A Touch Typer

Download NowName your own price

Leave a comment

Log in with itch.io to leave a comment.