top of page

Blog: Full-Tilt

Writer: Jack Stevenson
Jack Stevenson
Aug 25
5 min read

Updated: 2 days ago


ONGOING



Full-Tilt: Sprint 1

September 10, 2026


Full-Tilt is a pinball simulator roguelike where the player must reach escalating score thresholds to advance to the next round. The player will earn money after each successful round that can be spent on new machine components, upgrades, and other modifications. The player will need to strategically design their pinball cabinet to maximize score output as each level scales in difficulty.


Michael Musante, our team's lead designer, created our game's concept and recruited a team of 13 consisting of artists, animators, a sounds designer, and programmers, including me. I will be the lead programmer for this project, and I will be responsible for overseeing and assisting in the development of our game's codebase. I will also be responsible for maintaining the GitHub repository and upholding a workflow that allows our 2 other programmers and 2 level designers to collaborate without merge conflicts.


My first task was to set up our project's repository and onboard our programmers and level designers onto it. While I have plenty of experience with this in the past, I decided that we would try a new workflow I thought would be beneficial for our project: Trunk Based Development. Trunk Based Development is, as defined by its dedicated website, "A source-control branching model, where developers collaborate on code in a single branch called ’trunk’* and resist any pressure to create other long-lived development branches by employing documented techniques."



Instead of developers having individual branches with long lifespans, developers instead create short-lived branches off the main branch, or 'trunk', and pull their work back to it within a very short time (a couple days at max). This frequent splitting and merging allows for rapid iteration across a large team, where merge conflicts are caught and dealt with almost immediately as they manifest between branches; day-long conflict resolutions after merging are no longer a concern when the volume of changes per pull request is only a few days of work rather than weeks or even months.


I specifically wanted to employ Trunk Based Development due to the merge conflicts I had with my last Unreal Engine 5 project, DiveTime. Everyone on the GitHub for that game had individual, long-lasting branches that were infrequently merged together, causing massive merge conflicts that took an entire day to resolve. So far, Branch Based Development has been easy to both teach my teammates and practice during development, without any signs of complications.


GitHub repository that I made for the project.
GitHub repository that I made for the project.

Outside of the GitHub, there was only one IT issue that I had to deal with. For some reason, their computers wouldn't recognize their own installation of Unreal Engine 5.8.2. When opening the project, it would prompt them to change the project's version to one labeled with a randomized string that vaguely looked like a GUID. I eventually figured out that their installations didn't properly add a Registry Editor key with a path to the Unreal Engine 5.8.2 installation. After adding this Registry Editor key to their computers, it's been smooth sailing since.


Registry key that was missing.
Registry key that was missing.

With the GitHub repository situated and teammates starting work on their own branches, I pivoted towards configuring Unreal Engine's physics to allow for our pinball simulation to behave like a real pinball machine. I quickly decided that the pinball cabinet and components will be to-scale with a real pinball machine. I found both reference footage for the ball's behavior and online blueprints for a pinball machine for the cabinet's size.


Since our modelers were still working on the cabinet's base layout, I needed to quickly make a test cabinet to compare against my references. I ended up finding a black & white wireframe for a pinball machine concept that someone made online. I removed the overhang parts on the blueprint and imported the edited photo into Adobe Illustrator, where I extruded the layout into a mesh of interconnected walls with bends and obstacles. The complexity was important to better emulate an actual pinball machine compared to an assortment of walls made from cubes.


Then, I created a quick and dirty cabinet blueprint that spawned a pinball blueprint on a regular interval. Almost immediately I noticed how quickly the ball would come to a crawl after exiting the launch chute. I quickly realized that the surface friction was the culprit; turning it off made the ball behave almost identically to the reference footage. However, it came with the unfortunate side effect of the ball's rotational inertia appearing completely out of sync with the ball's movement. It also caused the ball to have a gyroscopic effect, letting it 'climb' against angled surfaces.


While I wanted the simulation to be as physically accurate as possible, I came to the conclusion that this wouldn't be possible without considerable engine modifications. Unreal Engine 5's Chaos is simply not designed with these smaller and more intimate interactions in mind. Since the lowered friction really helped the simulation, I decided to simply lock the pinball blueprint's rotation. Instead, it rotates a visual ball mesh based on the direction and magnitude of its velocity.


While not perfect in theory, the pinball performs closely to a real pinball in practice. Along with making the simulation asynchronous, forcing the pinball to use CCD collisions, increasing the simulation's tick rate to 120/second, and enabling physics subticks, the pinball blueprint behaves almost identically to a real pinball. The physics engine adjustments also fixed an issue where the player's framerate directly impacted the pinball blueprint's physical behavior.


With the two largest tasks of the 1st sprint done, moved on to creating a plunger mechanism for the cabinet. I chose to make the plunger using a physics constraint rather than through kinematic motion, as it would play better into the adjustments I made to the engine's physics and the pinball itself. It also allowed for me to very easily make the plunger's force vary based on how far you retract it before letting go.


Next, I started to import many of the 3d models that our artists had made. I had gained a lot of experience with Unreal Engine 5's asset import pipeline from DiveTime, so I volunteered to do it again for this project. Since all of our models would also have textures, I took the time to make a generic material that each of the models will use through material instances. I even added a few static toggles for enabling/disabling the use of certain texture maps, squeezing out extra performance for models that may not need emissive maps, normal maps, mask maps, etc.


After the currently completed models were imported, I moved onto setting up the rail tube components. The player will eventually be able to place these in the cabinet, but I first needed to make them physically compatible with the pinball blueprint. By carefully adjusting the scale and colliders of the rails, I got the balls to almost effortlessly move into the ramp intake and travel through consecutive rail tubes.


Finally, I implemented a limited pinball system that kept track of the player's currently stored pinballs, active pinballs on the field, and drained pinballs out of play. I programmed this behavior in our game's GameMode blueprint, since these attributes will directly affect the game's current state. I also added helper functions for fetching a reference to the custom GameMode blueprint, checking how many pinballs there are of each state (stored, active, drained), and for spawning the pinball at a given location (as long as the player has at least 1 stored pinball).


For the next sprint, I will continue to develop the GameMode blueprint with additional core functionality and essential game states. I will add a fail state for when too many pinballs drain as well as a core input blueprint for all other game systems to hook into.

 
 

Related Posts

See All
Blog: New Clairvaux Vineyard Tour App

New Clairvaux Vineyard: Sprint 4 April 26, 2026 For our 4th sprint, I continued to refine our app's user interface using the UI Toolkit and C# scripts. I placed and filled in POIs on the map, created

 
 
bottom of page