Game Tech Deep Dive: Reworking the Unreal Engine for racing
Deep Dive is an ongoing Gamasutra series with the goal of shedding light on specific design, art, or technical features within a video game, in order to show how seemingly simple, fundamental design decisions aren't really that simple at all.
In this installment, we hear from racing specialist Milestone, known for their work on the Moto GP and Ride franchises. Milestone's Ivan Del Duca (technical director) and Stefano Lecchi (lead physics engineer) discuss how they transitioned from an in-house game engine to Unreal, breaking down the technical tweaks they implemented along the way.
More than a year ago, we at Milestone decided to switch from our proprietary technology to Unreal Engine.
Producing games with our own engine and tools was a very streamlined and efficient process, but the cost of maintaining it on par with the continuous technological evolutions in game development - all while supporting new hardware platforms - was proving too high. It was time for a change in strategy, a shift in gear.
As a result, MotoGP17 will be the last game built upon our own engine and -- if we may be so bold -- it’s going to be quite a swan song. We’ve squeezed our tech like a lemon to pump out 60 fps, across both PC and console. It’s going to be quite a goodbye for the engine that’s been part and parcel of everything we’d done up till then.
Making the leap
Shifting to Unreal, however, has presented us with both challenges and opportunities. The first step was an in-depth analysis of our own technology designed to understand just what tools and functionalities we needed to port and what, instead, was already present in Unreal. After that, our R&D department busied itself creating a prototype of a full racing game that could serve both as a proof of concept, and as the foundations of our first Unreal-based game.
The prototype had to include all the major features, as well as some more specific solutions required for the first two products, in order to immediately address the risks associated with the transition. Unreal, despite being a very comprehensive framework, did not cover all the areas needed for a complex racing game. In other cases, it lacked some high level elements like data management or flow control.
It’s worth noting that some sort of database management is very important in our games - we have a huge amount of data, statistics, vehicle parts, drivers and riders etc. -- and Unreal's data tables did not seem sufficiently flexible for our purposes.
A matter of logic
The simulation of vehicles proved to be the most delicate part to address, however. Unreal’s physics system is built on top of Nvidia’s PhysX (for comparison, our engine made use of Bullet). However, we needed to define where and how to integrate our vehicle specific simulation within the engine. We generally divide the vehicle management into three sections:
- Gameplay logic contains high level logic: input filters, driving aids etc.
- Vehicle simulation is a middle layer and includes: tire model, engine, transmission, differentials, suspensions, etc.
- Physics Engine (Bullet / PhysX) is at the bottom and manages rigid bodies simulation, collisions etc.
The separation of these three sections is particularly important when it comes to the reuse and adaptation of different types of gameplay and, most of all, different kind of vehicles; it was vital for us to have a vehicles simulation that can handle vehicles with two, four or more wheels.
PhysX provides a basic vehicle simulation framework, so the first step has been to review it using the Vehicle Template provided by Epic. After a few tests, it became clear the simulation offered by the PhysX vehicle module was not up to our standards, as it seems developed for more “generic” vehicles like Halo’s Warthog.
Some solutions, however, were very interesting and well integrated with PhysX core, like allowing a specific integration step for vehicles running at a higher rate than the one of the scene. Vehicles simulation requires very small integration steps at high frequency to adequately compute and manage forces on wheels, suspensions and transmission but the rest of the simulation usually has not so stringent requirements. The fact that this approach was already in place really helped us a lot.
At this point, we had to decide if we want to re-write the simulation from scratch, starting from our existing code base, or modify the PhysX module to suit our needs, thus keeping the architecture set by Epic.
Both approaches had their respective pros and cons, but the initial lack of confidence with Unreal Engine and the prospect to be able to immediately interact with the physical engine has led us to choose the second solution. This allowed us to iteratively write our simulation code while keeping all the basic functionalities. What’s more, choosing the first approach would have resulted in a fairly long period with no visible results for the rest of the team.
In the process, our simulation code has gradually replaced parts of the PhysX vehicle module, starting from the tire model and suspensions to the engine management and differentials. Indeed, by the end, very little remained of the original code. However, the code structure has not been altered allowing us to benefit of future possible improvements made by Epic.
We have also kept the anim blueprint approach to manage various vehicle body parts so that we are able to use assets designed to work specifically with Unreal Engine. This is a great advantage when working with outsourcers because there’s no need to create specific documentation and it is easier to find people that already know how to model/set up a vehicle in Unreal.
Another problem we found during development was related to raycasts used for suspensions that often caused unexpected results. In almost all cases the problem resided in how raycasts were calculated or how the results were used forcing us to pay special attention in configuring the assets to avoid problems at runtime.
Proof is in the pudding
As the work progressed, it became apparent the necessity to enable technicians to verify in real time the behavior of individual vehicle components to ensure that everything worked as designed.
With our engine we used an internal tool called Beholder. Beholder is an application that connects to the game via socket and allows us to inspect values of almost all the game components in real-time and displays them graphically, like in telemetries used in motorsport. It was therefore necessary to create a similar tool in Unreal.
Luckily, Unreal provides a very good reflection mechanism that allows the user to access game data programmatically in a data driven fashion. The telemetry system also allows the designers to graphically monitor any set of values by simply indicating their path.
When it came to gameplay logic, the similarity between Unreal and our own engine made things much easier. The porting of the elements has been therefore rather straightforward.
As such, we were finally ready to start making our first two products with the new engine: MXGP3 and Gravel. They have both proven to be excellent tests of the choices we’ve made in the last few months, since they both feature elements that put them to the test; two and four wheeled vehicles, deformable terrain, vehicle damages, destroyable objects etc.
Thanks to the power of Unreal Engine the development has not had major hitches, although some solutions have been partially revised.
While choosing a game engine for a small team on their first title is a no brainer, the same can’t be said for a bigger company that already has a known workflow that gives proven results. The implications are massive and must be evaluated carefully.
In the end, we’re very happy with the results. We have rebuilt our production pipeline in a modern and efficient way.