Lightfield is a flying racing game with parkour elements and a novel approach on how to navigate the tracks. We released Lightfield in September 2017 on Xbox One and Playstation 4 followed by Steam in August 2018 with extended HYPER Edition features.
Lightfield was designed from the ground up to be on consoles, which we were hoping would give us a good visibility boost on launch. Most of our features were targeted about what players on consoles want and expect and everything was designed for the TV+couch setting.
We focused on simplicity and tried to get rid of as many game menus as possible. Joining and dropping out of local multiplayer sessions and switching between game modes like time trial and exploration should happen fluidly without menus and reloads. This is also what caused some headaches later on...
We are a small team of four consisting of two programmers and two artists. We already had experience developing games and interactive experiences, but none of our previous projects was on this scale or targeted consoles.
We started out on PC as our main development platform since it took a while until we had all the contracts signed and received our Dev Kits for the consoles. Thus we only started around midway through the project with the implementation of console specific features.
In our research we found a lot of talks about performance and optimizing gameplay for consoles, but what we were missing though was all the small and large details that come along when developing for consoles but that are easily overlooked: It's the little things players take for granted and that behave the same across all games like sign in behaviour or starting and joining online multiplayer matches.
In this post I will try to highlight some of those obvious but not so obvious features that we initially overlooked and underestimated when porting the game to consoles.
Lightfield was designed with the TV and couch setup in mind from the start. There is a group of players out there that is actively looking for local multiplayer games, and since we also like us some local multiplayer ourselves, we decided to make it a core feature.
Focusing on simplicity and trying to reduce game menus in favor of a more fluid game flow, it was important for us that players can join and leave the game pretty much at any time. There is no discrete local multiplayer mode, all you have to do is pick up a controller and press any button to join.
Having no discrete multiplayer mode made implementation a lot more complex when it comes to handling users and user accounts. We knew that consoles have user accounts but we were not aware about all the fine details, similarities and differences.
Every participating player in the game has a user and that includes the split screen players. At the beginning we only had one "User" that represented the connection to the platform libraries but soon after looking at more closely we realized that ain't gonna be enough.
We started with most of our integration on PlayStation where accounts are handled quite easily. Whenever you connect a controller to the console you have to sign in and for the duration of that controller being connected the user stays the same. So whenever a player joins active gameplay in split screen multiplayer there is already a user assigned to the new controller and stays the same user as long as the controller exists. All we had to do if the user/controller disappeared was to drop the player out of the gameplay.
Later, when we moved to the XBox One we realized that the whole concept of users is way more flexible and dynamic there. Users bound to controllers can change at any time, controllers don't necessarily have a user bound to them from the get go etc. That means that you have to keep track of the users that are bound to the controllers and thus to a certain player. We were quite simply missing a player/user/controller system as one piece that connected this information in one place.
The sign in flow on XBox One also impeded how our in game join worked. In the beginning, if a player pressed any button on a controller the controller joined immediately into gameplay since the user was already initialized at that point in time. Now, when the player presses a button we have to go through the full sign in process interrupting the gameplay which can take up to several seconds.
Consoles are multi user systems. So each user should be able to play the game independently of the other players. Meaning each player needs their own savegame. We started out with one monolithic savegame implemented as a singleton which is not how a multiuser system is built. Aside of implementation problems around saving into the correct save games when playing split screen we had to think a lot about game design choices.
What should happen if player A starts the game so their savegame is used, player B joins, they continue together, and after a while player A drops out, effectively letting player B continue with the savegame of player A. In our case we just accepted that but not every game works that way. So design your savegame system ahead of time and think of all the possible edge cases.
Ligthtfield supports asynchronous multiplayer in the form of player replays that are attached to their highscores on each track. These are downloaded and cached locally and whenever you are playing in single player time trial or race mode you are competing against the times and replays of other players on the leaderboard.
Technically that's not a big feat, and we had this system in place since a very early prototyping stage. From a legal/organizational perspective however all user content can be considered User Generated Content, requiring special treatment and additional systems around it.
First, users have to accept an EULA detailing exactly what we are recording and what we will do with that data. To be on the safe side we had the EULA checked by a local lawyer and translated it to all our in game languages by a translation service specialized on legal texts. And remember, each user has to accept the EULA. In split screen mode, if one of the users participating in gameplay did not sign the EULA we were not allowed to upload data.
User generated content has to be blockable for minors by their parents. If we now consider our style of gameplay: Player A, a parent, plays the game with all ghosts enabled and is just in the middle of a lap in time trial. Now at a random point in time a child joins in on a second controller by just connecting it, signing in and pressing a button. All over our game are now recordings of other players which we have to remove at that moment and block any upload of new laps for all players because we are not allowed to display such replays to a minor.
Users have to be able to report user generated content that violates our code of conduct or the guidelines of the platform holders. For the reporting feature we had to build an easily accessible list of replays being displayed at any moment with infos about the corresponding player and a button to report a replay. Plus we needed a system to review reports, build a block list and distribute the block list back to the players. There is not a ready made system from the platform holders for that so we had to build our own.
When we started out building the online multiplayer system no one of us had any experience building a online multiplayer game. We expected the challenge in developing the online multiplayer mode to be the networking code, syncing objects and running the game sessions. Thanks to the Unity multiplayer code we quickly had this working but were surprised about the complexity of the handling of online multiplayer sessions that comes on top of that..
If you are not an avid online multiplayer player you might have missed some of the finer details and features that consoles provide to start and join a multiplayer game. The system UI of both consoles provide direct access to all the online multiplayer features in your game. You can for example invite friends to an already running game session via the system UI on both consoles or join another friend who is playing online through the system UI. We at least had to jump back and forth a lot to find all the ways through the system software. Your game has to be ready at any state to receive an invitation from another player and react to that accordingly.
On PlayStation online session management is kept very simple. Just keep an eye out for a feature called "Play together" that builds a party and starts a multiplayer match outside your game and then just starts the game with the correct parameters set, a feature that we missed in the beginning.
Microsoft on the other hand, has a way more complex matchmaking and invite system. Mostly you can join and start the online sessions through the system UI which has more features than the PlayStation counterpart. For example it shows if your friends are playing online at the moment and you can join them through the system UI in their session. My best tip to prepare for this: play online games on the XBox One before you start planning your system. Play a lot of them, try to understand at which moment you can join and invite other users.
On XBox One every online game supports Voice Chat. Integrating that was not too hard but watch out, because this content can again be blocked for minors and has some finer details in the user settings.
In conclusion, I would recommend that in the early planning stages find games with a similar feature set and see how they solved and implemented those systems on the respective platform. Since they survived already the certification process their flows and interactions are already correct. This is really helpful because there might be some fine details you did not think of before.
Should you ever need a shoulder to cry on trying to get a game on one of the consoles, you can always reach out to me via email or in the comments below.
This post is part 3 in an evolving post mortem series on Lightfield: