A Mayor Problem

For our final project at The Game Assembly, we decided to make a 3D-platforming game. I worked on PhysX integrations, cascaded shadows, performance optimization, and the rewind mechanic.

Project Details

  • 10 weeks full-time
  • Created in a custom engine using DirectX 11
  • 5 Programmers | 3 Level Designers | 4 Graphical Artists | 3 Technical Artists

Rewind

I got the chance to utilize my specialization project for this game. The initial implementation didn't take too long because I had already designed the library to be easily integrated into the engine. Then it was only a matter of finding what data needed to be monitored and implementing logic for using the rewind with player death and respawn. At first, only the player data was recorded, but eventually I also included environmental hazards and most animations in order to make the rewind feel more accurate. Memory became an issue at one point due to the number of animated props, but I was able to resolve this when I realized I was recording a lot of data that didn't change during the course of a level.

PhysX

I added support for generating and cooking mesh colliders through PhysX.

There was an issue where the player would stutter slightly during movement. This was caused by the game being out-of-sync with the physics engine and I worked with another programmer to fix it. We added some interpolation logic for the player, which fixed the problem. Later on, when we added moving platforms, the same problem occurred when you stood on one. To fix this, we added a fixed timestep update to the engine and used it for updating the moving platforms.

Shadows

Directional lights shadows were implemented using a shadow map and later improved it by using cascaded shadow maps. PCF was then used to make them softer.

Optimization

We ran into performance issues once the levels were starting to come together. Whenever it dropped below constant 60 FPS, I'd look into where our performance was going. First, the frustum culling was bottlenecking the CPU. I changed it to a frustum vs sphere check instead of a frustum vs AABB check, which brought us back to our target FPS. We didn't have support for instanced rendering in our engine at this point, which I knew would become a problem, so I implemented it before it became a problem. At a later point in the project, our GPU started bottlenecking anyway. Using RenderDoc to profile, I found out that our skybox was the culprit. The cloudy background rendered far too many particles and ate a lot of our performance. I reduced the particle count as much as possible whilst trying to retain the same look. It also suffered from a lot of overdraw, which was easily fixed by changing the draw order. This got us back to our target FPS.