Runbow: Online Multiplayer for PC, Xbox, PS4, WiiU, Switch & 3DS
Runbow by 13AM Games is a colourful party-platformer-action game for up to 9 local or online players. It is currently out on Nintendo Wii U, New Nintendo 3DS, on Steam for PC, on XBox One, and coming soon to PS4 and Nintendo Switch.
This is the story of how 13AM implemented online multiplayer for its first version, on the Wii U.
9 LOCAL TO 9 ONLINE
Our earliest issues were related to adapting the 9-player local multiplayer to online. We wanted a single console to be able to go online with only 1 to 4 local players. This meant we ended up needing two different arrays: one for local players, which keeps track of the connected controllers in a console; and one for online players, that has to be synchronized across all connected machines.
There were many instances in the code where these arrays were getting confused, or didn’t update properly, and players would end up with the wrong numbers! Late into QA, we kept finding instances where local and online players would get confused, such as a local controller influencing what an online player was doing.
Overall, there were many systems we had to change, ranging from which local controllers could navigate online menus, to which online characters the game have to care about when counting stats and achievements.
JOINING THE GAME
Unlike the game’s offline modes, we don’t allow players to join in the middle of a game in Runbow’s online, both because it would be confusing for players, and because it made dealing with our player arrays too complicated. We added a screen where you choose how many local players were bringing before connecting to the servers. That way, our arrays knew consistently how many players would be in the game, instead of changing based on how many of the local players hit ‘A’ to join.
Even so, joining the game was very troublesome due to the amount of RPC messages that host and guests exchanged. It wasn’t bad with a lower number of players, but it increased exponentially as more players joined. For instance, this is how a new player’s information is distributed:
Player joins as a Guest -> Guest sends their info to the Host -> Host updates the session info and broadcasts it -> Guests tell the Host whether the info about them is still correct -> Host broadcasts the info again if it was incorrect
Those last steps are necessary for cases where a Host has disconnected and a player with incomplete information becomes the new Host.
We worked hard reducing the information we had to send in RPCs, and added a short waiting time between them. This causes the connecting process to be a bit slower for players, but it gives the Host enough time to process all the information. More RPCs, more spaced out, is a solid solution that got rid of the crashes and reduced data loss to a minimum. This way we can deal with cases specific to Runbow such as up to 8 players joining simultaneously through their Wii Us.
CHARACTER SELECT SCREEN
Too many messages were being sent in the character select screen, which players access as soon as they connect. Here, players can choose a character, colour and costume to play with. We didn’t want two players to have the same character, so we implemented a queue: when a player presses Left or Right, a message is sent to the Host asking for the next available option, and the Host sorts requests and answers them one at a time. This caused a small lag, but not too bad.
This system requires the Host to know which characters and costumes each player has unlocked. As this was too much information to send alongside the costume requests, we added it to the RPCs sent at joining time. To minimize the information being sent, we encoded it in three integers whose bits tell if each costume and character is unlocked in that console.
Nevertheless, the information being sent back and forth was still too much. We discovered that it was greatly reduced by removing a simple feature: remembering which colour and costume a character has after switching characters. Just having them go back to the defaults made it work. Sometimes you don’t expect which systems might have a big overhead, so testing all of them is very important.
One last security measure we implemented was closing the online rooms 5 seconds before the game begins. In normal cases, when someone joins, the timer adds 10 seconds to give them time to select a character. But if this happened in the last few seconds, everyone would transition to the game scene before the Host had updated its information with the new player, who would become an unintended spectator.
For most of Runbow’s development cycle, we had between 1 and 3 Wii U development kits at the office. Three were enough to test most of the online cases, but not all of them! So we used PCs to connect to the kits. However, performance in the PCs was better that in the Wii Us, so the testing didn’t reliably show how actual performance would be just with the Wii Us.
Photon’s network simulation ended up being really helpful for us to simulate cases closer to reality, such as high latency or data loss. And in many cases, we just had to assume the worst case and make our systems as robust as possible.
We learned that in networking the most difficult part isn’t the ordinary, but the exceptions. It’s not difficult having a player join the game; it’s difficult when 8 of them join at the same time. Perhaps the most troublesome area we faced were unexpected disconnections.
One of our improvements was the aforementioned step where Guests check if the Host’s information about them is true, and warn about mistakes if there are any. During gameplay, we repeat those checks at the beginning of every level. This lead to a bug when the Host disconnects during the last level of the game. Then the new Host doesn’t notice in time, and the game keeps loading the next levels in the build, eventually reaching levels never meant to be played online. We fixed this by having all games count the number of levels, and disconnect if it’s too high. Players briefly see a new level being loaded, but they are taken out of it pretty quickly!
We kept working on Runbow, and improving its networking, even after release. One of the biggest post-launch fixes was making level transitions longer to avoid desync that happened in consoles with a poor connection. It made the game a tad slower, but more reliable. Months later, we would increase the transition time even more for the New Nintendo 3DS version.
There’s a bug we managed to avoid but not truly fix: After a game was over and the players returned to the Character Select Screen, the information in the network would cause extra characters to appear in the screen and slowly drift to the bottom of the screen. We never figured out why, so instead we now force a quick disconnect and reconnect when starting a new game, which avoids the issue!
Finally, there’s one thing that we know we’ll do for sure next time we have to code an online system similar to Runbow’s: Make the players choose their characters, colours and costumes BEFORE connecting to the game. Not only it would have solved a lot of technical issues, but it would also be easier for players to identify who they are in the chaotic 9-player screen!
All in all, Runbow was an exciting adventure, but also a big and challenging undertaking. We were a team of 9, just out of school, just 2 programmers with little networking experience, and with a game whose base code was written during a game jam. Luckily, using Unity helped us port it to Wii U and be its first 9-player local game, and using Photon greatly simplified the process. Despite all the difficulties we found, our playerbase was really excited and thankful about online, and we learned a lot about it for future projects.
Technical and Narrative Director at 13AM Games