Bloom
Project Details
15 weeks, half time, completed in April 2023
13 people (6 programmers, 3 artists, 3 level designers)
Created with our custom engine based on The Game Assembly's in-house engine TGE
C++
3rd Party Libraries: DirectX 11, FMOD, Nlohmann Json, ImGui
7th Game project at The Game Assembly
Contribution Highlights
Table of Contents
Overview of the Nvidia Physx implementation to our engine
Building the PhysX SDK to match our project and implementing it.
Implementing a solution for a stable physics simulation with a decoupled framerate.
Creating a PhysX interface for the rest of my team to use.
Splitting game logic, render & physics loops to accomdate for physics implementation.
Allow animations to still run using deltatime to ensure speed of animations is not dependent of FPS.
Backend for the rideable Platforms, Enemies & Character Controller which is driven by PhysX
Implementation
Setting up the PhysX Actor from Unity
PhysX uses some different conventions than our engine and Unity. For example, PhysX calculates rotation of a collider around its center of mass instead of it's pivot point. These differences are taken into account when working with PhysX in our engine.
Takes full Game Object transform from our Unity scenes into to consideration when created.
All collision, Rigidbody & Physics Material data from Unity is translated into our engine.
(Import and Export is handled by another programmer).Allowing multiple colliders per object including offset per collider and is also updated accordingly in runtime.
Rigid Dynamic Component as a handle for our PhysX Actor import setup.
Level in our engine
Level in Unity
PhysX Debug Visualization Toggle for the team
Implementation of PhysX draw lines into our engine
Update transform of our game objects from the PhysX actor transform
As i mentioned earlier, there is special need to handle rotations and offset in a specic order due to PhysX conventions.
To handle all the game objects transforms & children transforms: myGameObject->SetTransform();
Was written by Christoffer Rösäter on my team; A skilled programmer & considerate teamplayer who I can highly recommend.
A solution for a stable physics simulation with decoupled Rendering
To achieve this i needed to have a good understanding of all systems that were used in our engine & of how physics simulations runs.
This blog post from Glenn Fiedler proved invaluable: https://gafferongames.com/post/fix_your_timestep/
From the above blog post I choose to implement the Free the Physics concept.
This also resulted in smoother rendering
Before
After
Callbacks in PhysX
Handling Triggers using Simulation Event Callbacks
Handling contacts for the player
Treating the message as reciever, this proved an easy way for my team to work against.
All of this above could be handled in a different way, however this proved an easy to use system for my team.
Performance was not an issue due to the smalller scale of the projekt.
On Contact Callbacks
A more sophisticated way of handling callbacks for detailed physics simulations would be done in the way displayed below.
On Contact reports contacts between each pair and provide collision data such as flags, normals & force/impulse. This would then have to resolved in a later step, preferably resolving them at the end of the frame for performance and stability reasons; any actor/game object would have their contact notified in the next frame.
I found no use case to improve our user experiene with this functionality based on the game we were making. But it's a core feature of PhysX so I wanted to mention it. This is how the foundation can be handled.
An abstract idea of how to handle it
State/Scene handling
For this project the previous system from Spite:Knight of Odin - State Handling was reused.
Implemented a state stack that can update and/or render several states as layers.
Easy to go between states without them knowing of each other.
Can render states behind the newest. Used for the pause menu when the game renders in the background.
Animations are living in game while game is paused.Each state will always run it's entire loop to it's end.
This is to ensure that there is no interruptions in the code that could create unexpected behavior.
Cached States
This system was designed to easily swap between levels and user interfaces that didn't require reload.
This gave us faster load times & an easy way to handle checkpoints.
The loading of levels was handled by another programmer.
*The video is from an early stage of development running in debug mode and without threading loading hence the slower loading times. The scenes that you see in main menu and credits were cut due to a request of our designers wanting the game to look more minimalistic. Functionality remains in the engine.*
Observer Design Pattern
For this project the previous system from Spite:Knight of Odin - Observer Design Pattern was reused.
Implemented a post master and made sure that only active states are receptive of messages.
PostMaster is also known as Listener/Observer system to enable communication between UI for example.
Made an automated system to remove observers so anyone working with system does not have to explicitly handle it, whilst keeping the functionaly to use it manually.
User Interface System
For this project the previous system from Spite:Knight of Odin - User Interface System was reused.
Built in-editor tools for Design to move around and save position using JSON.
Unique canvas for each scene, ensuring modularity.
Assets are cached while in-game settings is reset upon death or new game.
Responsible for sound options & resolution handling.
Checkpoints
Check point handling, reintegrating the player correctly into the game world on death.
Level Transition
Backend handling of scene transitions.
Scene Selection using ImGui
Debug tools for design.