Fling to the Finish: UI

The biggest challenge on the game, for me, has been to work on its controller layout selection UI screen. Yes, one single UI screen. Well, what use to be a single UI screen.

Video: improvements on the team setup screen over time

This has to do with the extremely complicated and flexible playstyle choice system that the game supports – two players can share two sides of the same controller, or they can seamlessly use two controllers separately. Add to this the fact that any player can choose to join any team, and that the system works in the same way in the online mode, and it becomes one difficult task to ensure ease of access while maintaining player freedom.

During the course of development, there have arisen many edge cases and scenarios that were unaccounted for, and that is bound to happen when one screen attempts to accomplish the behemoth task of: choosing player teams, controller layouts, and characters, and setting online lobbies, all in one single 2D screen. We could obviously do these tasks in multiple different screens, but as a team we decided that it made the most sense design wise to have this entire game setup be done in one screen, but in multiple steps.

But before I explain how all this was such a big challenge – and how it was resolved – I’ll first have to explain what it is that we were trying to achieve, and how it created more and more issues as we kept complicating the system while trying to keep it simple for the player.

1. Start (relatively) small

The very first iteration of the menu where players chose their teams was inspired from FIFA’s team selection screen. You have two sides representing two teams, you move your controller to either side to make your choice. Only in our game, TWO controllers could move to one side. If only one controller moved to a side, that would mean that the single controller would control both characters of the team (shared-controller layout), and if two controllers moved to one side, each controller would control one character of the team (separate-controller layout).

Separate layout (2 controllers) / single team

2. Add more ways to play

Sure, but what if a single person wants to control both characters of a team? Of course they can, but the moment their team gets flipped (the right character gets on the left side, and the left character on the right), they would have a very difficult time controlling the team because the actual controller layout doesn’t flip along with the team. This is resolved using a L & R prompt that shows up over the characters whenever they get flipped on screen, to help the player correct their orientations. So now we need a way to know if 1 or 2 players are controlling using a single controller, and the way we handled this was by adding the 1 or 2 players question right on this screen.

The character select at this time was a separate screen, and showed up after selecting teams.

This whole system, in itself, was difficult to implement, but still a fairly simple task when compared to future iterations of it. The edge cases that I wrote about earlier arose from unintended controller disconnections and reconnects. What if a team was formed using two controllers, and what happens if one of those controllers gets disconnected? Was this controller that just got disconnected on the LEFT side of the team, or the RIGHT side? These issues, in themselves, were not very difficult to account for, but as we modified the screen to account for more than two teams, these issues cascaded down, bringing a very large permutation of issues with them.

Shared layout (1 controller) / split-screen (2 teams)

3. Add online multiplayer, add more teams

Once we implemented online multiplayer, we bumped up the number of teams in a local party up to 4. This meant making a new screen to account for 2 additional teams. That part was fairly simple. We just had to take the existing screen code, and since it was pretty generic, make it 4 sided, instead of two.

The challenge now, was not making the screen account for more teams. The challenge instead was instead making sure that there were no latency issues arising from this system.

Latency, and accounting for the numerous edge cases that would break this system: some of them I thought of, some happened only when playtesting the game, because there were so many that it was humanely impossible for a small team of 2 coders to think of all of them. I say this because our online multiplayer builds on the flexible playstyle choice system:

  • Two players on two different computers can control two different teams, OR they can choose to share a single team. This means one person would control a character on team A, while the second character would be controlled by their friend connected via the internet.
  • Of the 4 teams that can be set on this screen, two can be set on the same computer. This means that split-screen is still allowed locally, but there may be two other teams other computers.
  • Of the split-screen teams on the same computer, both teams could be shared online as well. This means that one player in each team is on the computer with the split-screen, but the other two players are connected as the other halves of these teams from either a) another computer with a split-screen setup, or b) two different computers with a single screen setup.
  • For any team that is controlled fully by the same computer, that team can either be using a shared or separate controller layout. If it is using a shared layout, it can have 1 or 2 players in it.
  • All this information needs to be synced across all clients to avoid inconsistencies in data setting on all clients

This system can be broken by any number of unforeseen situations. I’m listing down a few:

  • Any controller might disconnect from any client on the internet, and that controller may or may not have been assigned to a team
  • A whole client might disconnect from the lobby, and that would be the equivalent of ALL controllers from that client being disconnected
  • There can only ever be a maximum of 4 teams. One client is not one team, or one player. One client can be anything from 1 player up to 4 players, and these 1 to 4 players can make anywhere between 1 to 4 entire teams or halves of these teams. So how do we know when the players are ready to progress from this screen?
  • All player inputs MUST be processed in the order of players actually providing input. This means sending client information to the server before processing it. If the order is broken, then data processing can fail and cascade into very big problems. But for someone with high latency, waiting for the server to process input can feel very unresponsive. Why is my controller taking so long to move to team 1 after I tell it to move there?

4. Make character selection a part of this screen

Selecting characters on a new screen eventually proved to be more annoying for players than it would make things simpler. What if while selecting characters, someone disconnected? And what if they were an online partner of another person in a team? Well, now this person needs to redo their controller layout selection. And the only way to do that? Return to the team setup menu. Not good.

So we made character selection a part of the team setup menu. Was it better? Yes. Simpler? Maybe not. Much, much more prone to bugs? Absolutely. The infinite web of edge cases that I mentioned earlier grew even more exponentially, to the point where it became impossible to even reproduce a bug. Yes, we saw the very obvious bugs, but were these bugs actual bugs, or were these a result of the system having broken 20 steps earlier, and then cascading into this much bigger, visible, issue? How do I even begin to trace back 20 steps? When I have traced those steps – and fixed that original issue – what is the guarantee that I don’t have to fix steps 5, 11, and 15?

The only answer I have to these questions is that I fixed as much as I could. I got the game to a point that was incredibly stable, and that’s how we launched the game into early access on Steam. To all of our surprises, this system worked fairly well, for the amount of trouble it had given us.

5. The final iteration

There were still issues with this screen. There was the occasional edge case bug report made by a player on Steam or Discord. There were more cases of players being confused how the system even works, and this was obviously not a good thing. Most importantly, players couldn’t matchmake directly into this screen. The only way to matchmake until this point was to first make all your teams, and then matchmake to try and find other teams, up to a total of 4 teams.

This meant there was no way to matchmake if you were looking for a team partner, and as such, no way to matchmake for the campaign mode. So we decided to let the players matchmake directly into this screen. However, at this point, doing all this in a single screen started making less and less sense. Also, moving 2D images of controllers and keyboards to 4 abstract quadrants of a screen wasn’t that great at conveying how that will reflect in gameplay.

So we took a leap of faith, and converted the whole system into a 3D menu system. Each controller now spawns a single character (separate layout) that can move around and enter a team along with another separate character. This character can also go over a button to swap into a whole team (shared layout). The team selection menu is still the same in concept, move a character or team to a team button to select that specific team. This now conveys actual gameplay to the players in a much more natural manner. I am controlling this character, who is part of this team.

Separate Layout, 2 controllers, Campaign Mode
Shared and Separate layouts, Race Mode

There is also no more need to do every single thing on a single screen. Fluidly change your character at any moment in the 3D system. Also – if the chosen mode is campaign, only a single team button shows up since only races allow for 2-4 teams. Campaign is limited to a single team. Players can also matchmake directly into the team setup, which means they can now find campaign partners.

Programming this system was surprisingly extremely easier when compared to all the 2D UI programming I did for the system. With no more need to sync UI movements across the screen, and with 3D rigidbody character syncing already implemented via gameplay, all I had to do now was to use all my learnings from previous iterations and write very robust architecture just for data syncing. Who is controlling which player and which team they are on. I still had to worry about latency and order of operations, but since I already had that figured out from earlier, I was able to transfer that knowledge into this new system.


As you can see, explaining this system without showing it work in the game is a massive task. Implementing it and making sure all the edge cases that would break it, don’t break it, is ten times as difficult. It wasn’t just making sure the edge cases worked, it was also about accounting for internet latency issues. It has been a 5 year long process that involved multiple iterations and constant bug fixing. As such, a majority of my work on this game has been spent on one single UI screen (well, now a fluid UX system). I say this has been the biggest challenge because this system is a combination of all the systems that go into making this game fun and accessible. It’s a very complex system that delves into concepts of hardware connections, inputs, networking and latency, and a very peculiar team-making concept.