Bubono's Bumperland was developed over the course of twenty weeks with a team of five people. I was the lead designer, project manager, and assistant programmer. We used Unreal Engine 5.5, Blender, Maya 2024, Houdini, and Adobe Substance Painter.



The idea for Bubono’s Bumperland started as my friend and I’s desire to mimic the fun she experienced in Tiny Terry’s Turbo Trip, in which you play as an unemployed creature who is inexplicably given permission to drive a car around town to “make money”. We wanted to create the fun of being able to drive around, bump off of things, and knock things over in a less-GTA style fashion, and more of a lighthearted tone.


Thus, the idea of driving around in a bumper car to wreak havoc in a theme park was born. I pitched my idea to a crew of peers I was hoping would be interested, and four of them accepted. I now had a team with a visual effects artist, a programmer, a 3D modeler specializing in box modeling, and a 3D/2D artist who specialized in character art and more organic shapes.

My initial pitch was to create a rogue-like run-and gun where as you smash through enemies with your car in an attempt to escape the park, you can gain different special moves to attach to your car, and by the time you reach the end of the level, the special ability you get will correlate with the specific enemy type you killed the most of.


That being said, when we came together as a team to discuss the game’s core concepts, my programmer and I decided out of caution that we may not be able to create an elaborate generative rogue-like system like we wanted within the time we were allowing ourselves. Thus, we instead decided to create the game with static levels, and your goal is simply to tear through enemies in your car in an attempt to escape each branch of the park.


Auto Engineering



The first and most important step in bringing this concept to life was making sure we could create a bumper car that was fun to drive. One of the main mechanics I knew we wanted to include was that of bumping, and influencing the momentum of the car dramatically based on what you bumped into. There were several factors to take into account here, as I spent the next several weeks repeatedly adjusting the car’s initial speed, maximum speed, acceleration, friction, and others until the control of the car had just the right amount of push and pull.



The main idea here was to actually make the car more volatile to control, as if you were a child putting themselves behind the wheel of a big rig. This was done to lean into one of the game’s core facets, which is that you must allow the car to be in a state of chaos in order to make progress. The car was no fun when you were able to perfectly position the car with every step, it was important for you to really be able to feel the weight of the car swing around, as if you’re just barely able to keep control of it. The player really needs to take into account how wide the car swings when making turns, and taking intentional time and space to slam on the car’s brakes in order to slow it down.



Anti-Crumple Zone



Through this idea, bumping was designed to accentuate this principle. I spent a long time trying to actually program the bumping physics so that bumping into walls actually sent the car at a proper reflection angle. There were many different ways I could have this but we ended up relying exclusively on Launch Character to propel the car according to a certain vector upon impact.



This was a long and tedious learning experience, and my results were giving me a lot of trouble in terms of sending at an actually accurate angle. During my first attempts at brute forcing, I settled on creating entirely square bumping walls, and manually setting the reflection angle depending on which side of the square you hit. I was determining the vector of reflection with a line trace and would Get Reflection Vector with the Break Hit Result, but I was having a lot of trouble getting this vector to be dynamically accurate on all sides of a wall, so I instead compromised by having the car calculate a specific kind of reflection angle based on the side of the wall you hit, which seemed to do the trick for now.

This is an early graphic I made for my team when set dressing our early blockouts, showing just how complex I had already made a simple mechanic.


This later proved to be an issue for several reasons, as not only was this incredibly inconvenient to manage when blocking out a large level in which we would need dozens of these walls oriented correctly, and we could only create flat bumpers. So, soon I went back to the drawing board trying to actually create a system that gave accurate reflection angles on any surface no matter the situation. The first thing I did was completely scrap this “correct orientation” system and force the game to adapt to any object no matter the placement. As long as an object had a “bump” tag, it should be bumpable. However, I frequently had issues with non-flat objects displaying an incorrect reflection vector when a line trace was shot towards said object.



This is because we consistently gave all of our meshes basic box collisions for efficiency’s sake, but since we wanted a pretty realistic reflection angle to come from a line trace interacting with an object, we had to compromise with many assets and use their complex collision, which would quickly affect performance if we were not careful. Further challenges presented themselves with the line trace being shot out either too early or too late and therefore getting the wrong angle of reflection because the trace had been fired off of an object from a different time.



Eventually, I had a system where when a player’s bumping collision sphere overlaps with an object, it will check for the object's “bump tag”, and then get the reflection angle of a line trace spawning from the car based on its velocity. Since we forced bumpable objects to have complex collisions and only checked for the line trace during the brief moment where the car’s “bump sphere” overlapped with the object in question, it consistently gave correct reflection angles at exactly the right time.



State Mandated Speeding



Once I had the actual physics figured out, I decided to change how physics would actually apply in this sort of interaction - since you would normally simply bounce off of a wall at the same force at which you hit it - to where no matter what speed you hit a bumper, it would propel you off of the surface at a fixed, much higher speed, to further send the car out of control. This was done to a degree that if you left the car in a square space entirely made of bumpers and ran into one of them, the car could bounce around the space like a DVD logo until the player forced it to come to a stop.



While it may seem like the player may want to avoid bumping into things in order to maintain control of the car, this was where it was time to introduce the push and pull of “losing control” of your car in order to make progress. A lot of, if not the majority of fun from action games consists of the player constantly putting themselves at risk in order to achieve a proportionate reward (e.g. exposing yourself to enemy fire to get a good shot at your target, getting extra close to a threat with a melee weapon in order to deal more damage more quickly, etc).



As such, the game’s surrounding mechanics are meant to lean into requiring the player to put themselves at risk (losing control of the car when gaining a bunch of speed) in order to achieve reward, which would be using the car’s speed to knock things over, make your way up steep slopes, kill enemies, and other things that would naturally require a lot of speed and force in order to achieve. This was the main idea behind almost all of the functional assets we created for levels, that we would use repeatedly to create different situations for the player to navigate. Slopes block off various sections of maps until the player figures out how to fling themselves at the correct angle with enough speed, allowing them to progress. This same idea drives the primary way in which the player achieves progress, setting up the right angle/bump in order to careen towards a target with uncontrollable speed.


Mud does the opposite, only blocking players if they hit the puddles with too much speed, forcing greater precision in certain sections. In others, the mud serves as refuge for areas in which the player has a much more difficult time maintaining control of the car.




The Drive to Drive



While I was filing down the details for how the car would move, it was time for my art team to create the world that the bumper car would wreak havoc upon. As bumper cars generally don’t exist anywhere outside of carnivals and theme parks, we decided that the player would be in a run down theme park, and - for the first level - the park theme would be medieval, as this would provide a wry contrast to the idea of an angry employee hitting random objects with a bumper car.



This was an important time to really establish what was happening, and why. What would compel a player to drive around and cause mayhem in a place of such fun, other than for the general sake of breaking things. This was at the same time we were mulling for a while on the name of the game, which I wanted to be whatever we decided to call the park itself. This is when I came up with the mascot of the park, stemming from the medieval theme of the first branch: Bubono the rat. The concept behind the character is that it was the primary animal I associated with medieval times, and especially in the days of the Bubonic Plague. This also allows us to poke fun at the Mickey Mouse character, while sticking to the theme of the park.

The idea of the protagonist being a disgruntled employee who desires to take their revenge on the park where he works was something remaining from the start, but the Bubono character really helped round things out, as we now have what is essentially the villain for the game. In the game’s story Bubono will be both the park’s mascot and the park’s CEO, and the player will be reminded of his existence constantly through posters, adverts, statues, and more.



Now we wanted to create the first area for the player to parade around, and since this branch would have a medieval theme, I asked my team to begin creating architecture that resembled medieval shacks and simple houses, that could be used for park architecture and could be easily molded with the theme, as we could turn them into restaurants, attractions, and more with just a few changes in texture.



We also wanted to figure out how the park would look on a wider, more shape-oriented scale. I say this because we know that the goal from a designer’s perspective is to force the player to ping pong around the park like a pinball and run into as many things as possible, and as such, a typical park layout would not typically allow for that. This is where we decided to stretch the realism of the concept slightly, and design the park around sections and placements of assets that would create the most amount of interesting interactions that the player could have with our different assets. This is also where the idea came up that perhaps the park should be more organized like a giant actual pinball machine, with the surfaces all facing downwards to perpetually send the player down the board if they don’t maintain control of their car.



Thus, the level design began to revolve more around where specific assets were placed and where the player was forced to go, rather than the actual shape of the park and the direction the player was heading towards. These two elements of the early level design would soon prove to be difficult to work with and were later significantly altered.


After much discussion we decided to develop the project with the idea that we would have three different park branches that would serve as levels. So, it was time to create each level one by one, and to do so in the context of my newly created short term goals (explained in level design document linked below).



Translation Fluid



One of the earliest things I knew I would be dealing with was the partial language barrier I would be working with being on a team where the majority of people only recently learned english, and were fairly soft spoken in general. This challenge was further accelerated by consistently conflicting schedules, forcing us to usually meet over voice calls. This meant any time anyone had a fuzzy mic or was in a crowded environment, I would be asking for people to repeat themselves over and over to no avail.

Over time, however, I began to get comfortable with different methods of communication with each member. Our primary prop artist was much more fluent and we would generally be on the same page the quickest out of anybody, and this became one of the better ways to communicate very specific ideas to the rest of my team. For my character modeler and assistant prop artist, getting reference images and drawing on top of them became the best way to get ideas across. I had to keep in mind that whatever reference image I sent and whatever changes I would ask for, she would take absolutely literally, and she would take any space for ambiguity into her own direction, even if it conflicts with our established style. So, making sure I had every ‘I’ dotted and ‘T’ crossed in describing what I would ask to change in a reference image was incredibly important.



I had similar communication barriers with my primary programmer, but we found more often than not, we could tell what the other was thinking. In addition, we had another strength in that our focuses were much similar, with both of us being programmers. This meant I could suggest features or additions through specific functions or Unreal components, and we could move our ideas much quicker.



This was a small version of something I learned quite quickly: if you want to move quickly, do not assign someone a task when it’s another team member’s strength. We play to our strengths, and we work around our weaknesses. This mentality also shaped how we developed the project in general. I soon learned that trying to put anyone, including myself, into an area where they are not comfortable was almost always less efficient than simply pushing their strengths and waiting for whoever is more suited to take over an important task to do so when they can.


Our team met online every day at 8 PM with 3-4 days a week of in person meetings alongside the online meetings. We ran two week sprints averaging close to 200 hours of work per week across the whole team. Each meeting I went over my work I had done that day, how long it took me, and what I was planning on doing next, and then I asked the same from each of my team members.



Of course, our work pace was frequently imperfect, and there were times where some members were consistently not showing up with the amount of time work they agreed to the previous day. Some of these cases were things that were clearly more complex than simply putting in hours, and in these cases we discussed more in depth about how long we could expect these things to take. Fortunately, the more complicated tasks were usually programming tasks, such as creating a more complex enemy or a general mechanic, so I had a much easier time discussing what we thought a realistic timeline for that task was (and, there was the option of me giving it a second pair of eyes).


When there were times where certain members were giving me an inconsistent work output, I would try to frame my response with the context that as long as the work we agreed to on the sprint sheet was fulfilled, being behind wasn’t necessarily a problem. However, I would still insist on daily results, as I wanted to be sure we were always on the same page, especially when it came to the game’s art. I always wanted to be sure there was something each day from everyone that we could comment on, and if someone was behind, my response was always that of “This is not a problem so long as you can do both today and tomorrow’s work by the time our meeting comes”. Additionally, my team members were well aware what long nights await us at the end of each sprint if we did not maintain our pace throughout the week.


When there were times where certain members were giving me an inconsistent work output, I would try to frame my response with the context that as long as the work we agreed to on the sprint sheet was fulfilled, being behind wasn’t necessarily a problem. However, I would still insist on daily results, as I wanted to be sure we were always on the same page, especially when it came to the game’s art. I always wanted to be sure there was something each day from everyone that we could comment on, and if someone was behind, my response was always that of “This is not a problem so long as you can do both today and tomorrow’s work by the time our meeting comes”. Additionally, my team members were well aware what long nights await us at the end of each sprint if we did not maintain our pace throughout the week.


During the project’s development we had a very tumultuous relationship with Perforce, as we repeatedly encountered bugs that even admins we contacted had no idea about. When team members checked out assets, they would find that despite having only worked on one computer, Perforce would act as if they were checked out on some unreachable computer, and it would be impossible to modify them again. Again and again files were cast into limbo and we were forced to duplicate them and replace all references to them, an extremely tedious process. In other cases, files would somehow be checked out twice at one time, by two instances of the same user.




These problems led to us restricting access to the project as much as we could, and only me and our primary programmer would regularly connect to the perforce servers, and all art assets and otherwise we needed would be sent to one of us to add to the project directly.



Finish Line Changes



Eventually we ended up with a level that was essentially just a giant box and the goal was still to simply “leave the park”. Upon extensive playtesting, while people found the mechanics to be generally interesting, time and time again we heard that the level didn’t make any sense and they didn’t know what they were supposed to do. This was about when the original vision I had for this project began to fade and a new idea first took shape.



I realized the problem is that our core mechanic did not mesh all that well with my idea of the game’s goal. I was trying to create a gameflow that involved both ping-ponging around a space and racing to a goal point as fast as possible, which proved to be unmotivating and confusing when it came to the playtests which we ran. How could we take what we had and turn the short, medium, and long term goals into something that was both more compelling and aligned with the mechanics we created?


The answer lay in assets we originally just created as side pieces to create the air of being in a theme park adjacent space, being the vending machines and food carts that are easily knocked over upon impact. We needed a way to tell the player that they were wreaking havoc and making progress in an easy to process way. So, we changed course to make the goal to be to break as much property as possible, and we would track progress based on how much stuff had been broken. This is when I had to develop ramming and breaking obstacles to be as interesting and satisfying as possible.



Naturally, different objects should require different things to take them down, and the first factor to take into account would be speed. We knew our UI would already need to take a few different things into account, namely speed and the player’s health. Since we knew we wanted to use different speeds to take down different objects, we needed some way to show how fast the player was actually going. Our initial thought was to create a UI that was essentially a speedometer, and include gages for speed health, and our (to be developed) special ability meter.



While we were satisfied with the idea of the speedometer, using this visual at the bottom to refer to an attribute that was both very important and constantly changing proved to be too cumbersome, even in regular playtesting. The time it took to dart your eyes from the car to the bottom of the screen and then back to the car was simply too much for the speedometer to be useful. Thus, we had to come up with a way to communicate the car’s speed essentially on top of the car’s model. We tried several things to pull this off individually. At first, we simply applied an action line effect to the car whenever it hit its initial max speed, but playtesters hardly noticed the change and thought it to be purely visual and insignificant if they did.


In addition, this would be a binary communication method of communicating speed, a far cry from the much more dynamic dial we had previously. While we did have a numerical scale on our speedometer, we also decorated it with a color scale from red to green, and this served as a great opportunity to communicate a value quickly and flexibly. Using a red green scale, we began to light up the car directly based on its speed. Not only were we able to take an asset off the screen that was taking up nearly a third of the player’s eye space, but this was much more quick and elegant to communicate. Even though we had fixed our eye space issue, we had issues figuring out how to distinctly communicate different speeds and how much speed different objects required.



This is when I decided to make speed requirements much less dynamic, and came up with the current ‘3 speeds’ system. While the car’s movement is still just as dynamic, the way the car displays speed and the way certain objects interact with speed will only check 3 different values: speed above 0 (red), speed close to the car’s natural acceleration (yellow), and high speeds only attainable via bouncing off of walls (green). We would then light up the car with distinct shades of red, yellow, and green, and objects would only be receptive to these degrees of speed. This further came together when we re-added a much more visible version of the action line effect, to only play when the player hits ‘green speed’.



This was also an important moment to figure out how to communicate required speeds to players on individual objects. My first thought was to color code objects accordingly in their initial designs (e.g. green benches for green speed, yellow construction signs for yellow speed, etc). However, I quickly hit a wall with this approach, as not only was this not a proactive way of communicating requirements to the player (and therefore more easily missed), but I’m easily boxed in for my choices of assets in trying to make them fit this color scheme. So, I instead decided to rely on flashing an overlay material in the style of an outline over any asset I like for about a second or so. Provided I kept the outline thick and bright, it proved to be something that immediately made playtesters think: “Hm, there’s something here, I need to pay attention to this.”



This was a big moment for more concretely establishing the game’s ebb and flow, and having consistent fun short term goals. There were multiple layers we used in order to make impact as satisfying as possible, and each addition we made we scaled with the weight or force needed to break an object. We used particle effects, screen shakes, animations tied to the object being impacted, sound, and animations tied to the UI. We attached two different particle effects to the point of impact, a simple action line effect and a more comical, emote-esque effect to re-enforce the whimsical atmosphere.



Screen shakes were added and scaled according to the force needed. I also created simple but goofy animations onto each object, less so tied to the force needed but distributed across the different abstract object types. For example, a hotdog cart will fly into the distance like a beach ball, but an outhouse will spin around like a top before both of them explode.



My sound team created a set of impact sounds which we randomized upon impact to keep things interesting. Finally, we remade our scorekeeper that was originally a 2D UI element to a 3D model. This allowed us to easily and dynamically animate the UI to match the significance of whatever object you were breaking.



In order to more cohesively structure our asset placement and to provide further reward to players who are planning out their moves, the game features a combo system, which amps up the amount of points gained by breaking things if done in quick succession. If the player knocks over amenities back to back without .75 seconds going by in between, a multiplier will be progressively added to the score gained for each proceeding asset hit. On the second asset hit, a 1.1x multiplier will be added to the score gained. On the third asset hit, there is a 1.2x multiplier, on the fourth asset, a 1.3x multiplier, and so on and so forth.



If asset placement allows it, this can let the player rack up crazy high scores from just one interaction. Theoretically, if the player doesn’t understand the system, sections and levels can still be completed just the same without any combos, but getting one or two big combos can instantly clear a huge section. Score requirements in different sections of levels dynamically change according to the player’s current score, so one good run will not automatically clear an entire level.



You can read more about how I used the combo system and these other aspects to construct the game's levels HERE in the level design document.