Bringing Chariot to SHIELD
Chariot is a couch co-op platformer that can be played alone or with a friend. Players take the role of the brave Princess or her faithful Fiancé as they maneuver the departed king’s coffin-on-wheels through 25 levels set in 5 vibrant underground environments, with his majesty’s ghost giving them a piece of his mind every step of the way.
Filled to the brim with emergent physics-based gameplay, Chariot offers hours of exciting exploration, fast-paced ride sequences and mountains upon mountains of loot!
What Went Right?
At the beginning of the project, we were told that the NVIDIA Shield TV was a powerful device. To be honest, we were all skeptical because, frankly, all available Smart TV devices to date were running on low-end hardware. That is understandable, as these devices are usually meant to consume online videos and simple apps, not much else. However, the first time we ran Chariot on the Shield TV, we were blown away. The game was running at a steady 60 FPS @ 1080p in debug mode, which is far better than the last-gen consoles. Memory was also not a problem, with 3GB of RAM. From then on, we knew that we could cross optimization off our list of tasks. Chariot is not the most demanding game out there in terms of processing power, but having a steady 60 FPS is a necessity for physics simulation, which tends to behave somewhat differently below that level. We had a rough time reaching that goal on some other platforms, but not on the Shield TV, thanks to its state-of-the-art hardware.
The internal memory of the Shield TV is very fast. There's practically no loading time at all. Even when the game is moved to an SD card, the loading time is pretty much on par with any console version.
NVIDIA has been great. They sent us devices on which to develop and test our game, and they provided a helping hand when we had problems with the Google side of things.
Chariot was built with our in-house game engine, which so far only supported the OpenGL ES 2 mobile graphic API. That way, we could reach as broad a range of devices as possible. That meant no MRT (at least not without using odd extensions). However, the game was built with deferred lighting and many post-process effects, so MRT support was a necessity if we wanted to keep to exact same look and feel as on other consoles. Thankfully, targeting the Shield TV has allowed us to move to OpenGL ES 3 which supports MRT out-of-the-box. Adding support for it was relatively easy, as OpenGL ES 2 is considered a subset of OpenGL ES 3. We just needed to add new code for MRT support, and that was it.
Our game engine has a platform-agnostic shader language, so most of the shaders worked as is. However, the devil is in the details and that's what was challenging here. We had a lot of small visual glitches here and there, not necessary apparent to the untrained eyes. Finding them in the game was one thing, but trying to understand the problem and fixing it was another. Sometimes it was just a wrongly signed parameter, but at other time it could be a precision or a texture compression problem. Thankfully, the NVIDIA Graphics Debugger was of great help to tackle this task.
Chariot is a console game designed for current-gen consoles, with their massive amount of memory and disk space. So we were not shy on using very large texture sets. Space saving was of low priority. However, on Android, Google doesn't allow packages bigger than 50 MB. We had to implement APK expansion files. Basically, all game assets need to be taken out of the main application package and bundled into a separate expansion file. The game engine needed to be modified to support the downloading and management of these file, and all assets loading needed to be rerouted to this new location.
What Went Wrong
Google Play Features
Chariot supports a few online features, such as leaderboards and achievements, which are linked to each supported platform’s corresponding features. So it just made sense to support Google Play Games on Android. However, there were some missing features that we had taken for granted on other platforms, which resulted in just an ok experience on the NVIDIA Shield TV. First of all, you can play any game on Android without a user profile (G+), which is problematic because achievements and leaderboards are tightly associated with it. So we had to disable everything when no profile was selected. The save games were not really affected by this because they are local-only. We also thought that when the user was going to be offline, the Google Play Games service would be nice enough to continue to work and cache the information locally until an online connection was available again. Well, it doesn’t work like that. In fact, it just doesn't work when you have no Internet connection. Unfortunately, the achievements you unlocked while offline are lost as soon as you get back online. We did try to create some sort of offline caching of our own, but resolving the offline data with the online one was tricky, in part because the save games are local-only and not tied to a profile. So we dropped the idea. All in all, we believe that it was something the platform should support out-of-the-box.
One other thing that puzzled us is why you can't reset a published achievement in the developer console. It's true that there's a REST API to do that, but you need to create a Web app and be logged with the user for which you want to reset an achievement. This isn’t very practical when you have offsite testers. One might say that you should wait for the game to be ready before publishing your achievements. Well, the rule is that you need to publish at least 5 achievements before you can publish your game in the Alpha or Beta channel, and you can't access any Google Play Games features if your game is not published. So you’re stuck from the start with that constraint.
This blog was authored by Bruno Cadoret