In this final blog post for the module, I will talk about the work I’ve done implementing a player controller. This changed drastically through time, and even the implementation I have now is in a pre-alpha stage (i.e. I would not want to let the design team play around with it, in order to avoid giving them misconceptions such as “oh, flying using pitch/yaw/roll is not fun, we should redesign the controls”). Therefore, I think it’s worth covering the implementation only briefly, and instead I’ll steer this post towards the discussion of using Physics Engines vs. Moving stuff via transforms yourself, as I feel this is worth reflecting on more than anything else.
This class implements the controls of a ground vehicle and is now kind of obsolete, since we’re doing 3D flying drones now, but since it’s still in the project, I might as well cover the implementation of it.
The key resource that helped me implement this was http://www.iforce2d.net/b2dtut/top-down-car which made me realise that a car made out of a single rigid body has basically the same physics as a single car tyre. Even though this tutorial was done for 2D, it was easy enough to adapt it to 3D. The key thing to realise is that we want to the car to not slide around. I tried doing this with frictions and masses initially, but that didn’t help much.
So instead (following the tutorial), I figured I need to ‘kill’ the lateral velocity of the vehicle, which is what the first bit of the code snippet does.
Afterwards, I simply take the inputs and apply an impulse forwards to speed up, and an angular impulse to steer.
A video of this can be seen here:
This is the more recent controller which tries to mimic controls of a real drone. It’s in very early stages though, and I’m well aware of what’s broken about it, but here’s how it looks:
The idea was for the “drone” to automatically stabilise itself once input stops (which I figured might assist the player in trying to control this thing). I guess that is the only interesting thing in the implementation, since everything else is just applying torque in a given direction based on input.
To stabilise using a physics engine, I need to figure out what torque to apply to align the drones local up axis with the world up axis. To do this, I figure out the angle between the axis I’m trying to stabilise (either X axis or Z axis) and the horizontal plane by taking the arcsin of the dot product between the two.
This is kind of where the issues begin: arcsin is not a precise function and with values towards 1 and -1 the output can jump rapidly. That’s why I cap the since at -0.95 to 0.95 to avoid crazy numbers. This is ugly and bad, and I realise this, and I will be discussing that aspect of my code in the next section, but for now lets carry on with the implementation.
To calculate the torque needed to bring the vehicle to an upright position, I use the equations of motion for angular acceleration:
Well, I kind of “half” use them. I apply these at every frame when there’s no input with a constant timestep that does not represent anything meaningful other than how fast should it try to stabilise.
This results in the controller overshooting sometimes and this is just the early stages of the controller done in a couple of days, so it shouldn’t be viewed too seriously.
I would also like to change this controller so that it would seek the rotation of the analog sticks, rather than the analog sticks defining the rate at which it rotates. So that a fully tilted analog stick might rotate it to 90 degrees sideways, and releasing it would make it come back to the upright position. I think this would be a way to make it much easier to control and is my immediate goal.
In general, this implementation is probably going to be completely re-worked, as it’s very experimental at this stage, in the spirit of playing around with torques and trying different things out, rather than a finished (or even half-finished) product.
What now – Physics Engines and Direct Transformations
Having to figure out angles from imprecise trig functions is certainly not ideal. My lecturer, Zafar, and me myself both think that implementing these controls using direct transformations would be easier. After all, I could just use quaternions and slerp to rotate in a nicer and easier way.
The trade-off is that if I do that, we might have to abandon using a physics engine for collision resolution as well, since direct transformation manipulations lose information about inertia in the object, which is key to resolving collisions. So if we went down that route, we might need to implement a simple collision solver instead. It’s not immediately clear which approach would be more time efficient.
On one hand, there’s spending time trying to implement these behaviours using physics, on the other hand, there’s spending time coding a collision solver that might cause issues periodically down the line: it’s simple enough for, say, 2 spheres colliding, but it might well get more difficult if we find that more than 2 objects collide in a single step frequently in our game. If this was the case, we could easily spend way more time trying to enhance our own physics solver to a satisfactory standard. Also, spheres aren’t the ideal shapes for drones – Oriented Bounding Boxes (OBBs) are, and solving collisions for them might be trickier. Admittedly, I’m pretty much a complete noob when it comes to collision solving, as my experience is limited at writing a solver for AABBs in 2D.
I think the best course of action would be to have a serious discussion with the team about how we would like to go forward. I hear that Sunny is interested in doing Physics Programming, so maybe it would actually work out well to implement our own solver.
Otherwise, if we do continue using the physics engine, I think PID controllers warrant a look: https://en.wikipedia.org/wiki/PID_controller , since their basic purpose is to minimise error (i.e. stabilise things), and I should probably try to implement that.
To sum up, it’s unclear which direction we should go in at the moment, but we need to do more research into both approaches, make up our minds and we should do it as a team if anything.
Finally, I think there’s a lesson to be learnt in terms of me having to scrap my ground vehicle as well. If I did it again, I would not have rushed to implement one at all. It would sound very strange, as that effectively bars us from getting a prototype out, but when the design of the game is as unstable as it was in our situation, it might be worth holding out and instead investing my time into other sure things that the game needs, such as menuing, scene switching, VFX, graphics, audio, tools and other general improvements to the framework.
None due to NDA.