Third person shooter - Flare
For me, this project has been all about physx! I feel it is very connected to gameplay, and the better it works, the better the gameplay. I have never worked with physx, and barley worked with any physics in 3d or c++, so this was a huge challenge, but it was incredibly fun and taught me a lot of valuble things!
Flare is about a person who has crashed on a mysterious cold planet. With a flare gun as his only tool, he needs to get to a high spot, shoot a flare, and hope his friend see his signal. To get to the highest spot on the map, he needs to solve puzzles and avoid predators.
This is the first puzzle, the character called 17 needs to get to the gate. The gate is quite far up, he cannot walk, climb or jump up there. There is only a buffalo, and a button in this area.
17 lures the buffalo with his flares to step on the button.
Doing so raised a platform that he can walk across
Now 17 can walk across the platform to the next puzzle
Doing all of this gameplay requires the buffalo to be able to trigger events where it physicaly stands, the player should be able to stand on a moving platform, or a platform that has been moved, it requires the flares to collide and stick to the enviroment, and most importantly it requires a player to be able to jump and walk around a physical enviroment. That is why i, for this project decided to work with physics, since our engine does not have a physics system
Our school was nice enough to provide us with a physx wrapper. We simply added this physx project to our engine solution. It was made for 2d and only had rigid dynamic bodies, so we added a rigid static body, and a rigidbody component for our ECS
The rest of this journey of implementing physx is just a matter of learning how physx works, and how to implement it in our engine. Alot of things are already made for us inside of physx, we just need to make a lot of wrapper classes to get it visualised in our engine.
This the init function for making the rigid dynamic bodies. The class just holds a body, then on the first line you can see that physx just creates it for us. setting all this up was fairly easy, and now we have colliders in the physx scene(not the scene in our engine, physx uses it's own scene). We added a few rigid bodies, and put them in the scene
Yeah this looks pretty trash, for some reason the turn all over the place, it feels like the rotations are very very wrong
Physx uses quaternions for rotations, our engine does not... We discussed in the group if it was worth us changing to quaternions for every rotation. But i felt we needed to do some research before making that decision.
I did some research and decided that it was too much. If we changed to quaternions it would just do math that we are already doing in level loading more complicated.
I did this method, to convert the quaternion of the physx actor, to an euler. For level loading this would not work, we would need a radian to quaternion to set the rotation of rigid body statics.
But it works well and good for rigid body dynamics. Because the rigid body sets the models rotation, instead of the other way around.
These are the cubes with a little better rotation, I showed this to my teacher and he told me to get a physx debugger to see the physx scene aswell
I got the debugger and we found lots of bugs, one being that our engine used centimeters as a metric, while physx used meters, i didint understand this at first. The yellow cubes are sleeping, and the green cubes are active. at first all of them were green and moving slightly. But once i figured out that physx worked in meters it was just a matter of multiplying by 100 at a few places, and now the bodies actually sleep when they are supposed to
This is the physx system inside the game that updates the visual representation of the rigidbodies
It sets the position, and rotation, with a few exceptions.
If it's a platform, the rigid dynamic body should be kinematic. meaning it cannot take external forces.
and if the tag is buffalo, it should lock its angular rotation in the x and z axis.
This might seem like a weird solution, but this is how it looks currently. If we had time to fix it i would, but the game need to be playable!
Physx has a nice virtual method that we could override, called onContact. We can see when and what colliders contact eachother, and then add behavior. Everytime 2 colliders contact eachother, we send a message to the post master, with the entities that collided.
For volume triggers, there is a similar method that we use. Instead of just sending one message, we send when the trigger enters and exits.
The physx system recieves the message, and handles the contact. In our game you shoot flares, and when the flares contact a surface, they stick. We could add that behavior specific behavior of the flares in the recive method of the physx system.
And for volume triggers it is pretty much the same story
A volume trigger system recieves when a trigger has happened and then handles that trigger. For volume triggers in our game, we handle them in our node script editor.
I've talked a little bit about how the flares stick to surfaces. But there was a major bug with them in the beggining. When you shot a flare, it moved so fast, it passed through colliders.
That's obviously bad, after reading the physx documentation for the 4th time, i found continous collision detection.
When a body has continous collision detection, it does more checks for collisions, which makes it more accurate, and doesnt let fast moving object pass through walls.
Before you set bodies to have continous collision detection or CCD for short, you have to enable CCD in the physx scene.
After that, you enable CCD on your bodies, and now flares dont pass through walls!
Another large issue that i talked about in the beginning was rotations. Physx uses quaternions, our engine does not.
To load in rigid statics, that dont move with the physx system in our game, we need to be able to set the rotation of rigidbodies accuretly.
We load in models from unity, which have quaternions for rotations aswell, then we change that to eulers that we set on our models in game. With this in mind, why not save the unity quaternion, and set the physx body to have that rotation?
This is how the pipeline used to look, we convert the rotation twice
There was some sort of conversion issue, but when you remove the middle step and just feed the quaternion to the physx body, rather than converting back and forth, the rotation is never changed, and it just works
Another feature we wanted to have was ridable bodies, such as moving platforms, or rotating platforms. This didint work at all in the beginning, but you just had to change a flag, and add a method to the physx wrapper for it to work.
Took me a long time to find, but all you had to do was to add this in the getBehaviorFlags method.
This also works for platforms that are moving verticaly, not just rotating platforms.