It's interesting to me how the physics bugs such as characters and object getting stuck inside walls, flying cars, failed inverse kinematics and so on have been the usual bugs for so many years now, but there isn't yet a methodology to prevent gamedevs from falling in those old known pitholes. These are very difficult to detect by QA and the way to fix them is tweaking some parameters and geometry here and there. There should be a way to supervise the physics engine, find whether future calculations will cause an invalid state on some object and choose a transformation that won't produce such conflict.
As with everything in gamedev it comes down to one thing: performance. Anything that can be faked, approximated our outright hacked in the name of perf or memory will be.
The canonical example for me(which was ironically is in Half-Life) is that the AI for the grunts is surprisingly simple. If you throw a grenade they were scripted to shout "grenade" and navigate to the nearest nav node.
Tons of people thought there was really complex AI behind that behavior but it was just a couple of really well telegraphed "if()" checks.
This anecdote reminds me of the AI in the original F.E.A.R game as well, which did something similar. The actual AI good on its own, but their barks did an -amazing- job telegraphing their behaviors. Like if they shout "flank him!" and then flank, you know because they announced it that the AI made the conscious decision to flank and it wasn't just some NPC incidentally wandering into a flanking position.
There's a talk somewhere about the F.E.A.R. 1 AI and there were two key changes made in the development: 1) it was restricted so that only a handful of actors can actually attack the player at the same time 2) introducing loud radio chatter because playtesters grew frustrated dying over and over to the AI just flanking them quietly. Before these changes playtesters were frustrated because they thought the AI is cheating (which it isn't).
Some devs do focus on it - this blog post goes into detail about how someone worked through making sure you could walk everywhere in The Witness: https://caseymuratori.com/blog_0005
Testing things like that is a little weird - they're inherently fuzzy, so even if you compare to a ground truth like a serious MBS package you're spending needless FLOPS on accuracy no-one will notice.
I guess if you are able to formulate the problem as a state machine, you could use something like bounded model checking to ensure it doesn't blow up, but the problems there are twofold: Firstly, that's way too complicated and brittle for a game codebase, and secondly your average game developer probably doesn't even know what it is to begin with.
> There should be a way to supervise the physics engine, find whether future calculations will cause an invalid state on some object and choose a transformation that won't produce such conflict.
This is probably just me not really understanding the domain, but this sounds like a version of the halting problem?
Even if it’s not, isn’t that just an extra layer doing what the collision engine is meant to do in the first place? And if you can monitor a system to ensure correctness, couldn’t you use a similar mechanism to make the original system correct to begin with? And if you can’t do that, how can you expect to make the supervisory layer correct?
Let's say when a cylinder of the car, a wheel, bumps into the infinitesimally sharp edge of the road, it could somehow result in a "singularity" that launches the wheel, the vehicle and its occupants to the sky, and that could be a perfectly valid result of that algorithm. The algo's task is not to determine whether that produces some "weird" animation from the player's perspective.
For that reason there should be a "user level" interpretation of the physics engine results, looking ahead in time and correcting.
What I’m failing to articulate is that it seems like if you can reliably look ahead to detect a “weird” but technically valid result of the physics engine, you’ve also detected the flaw in the physics engine that led to that result. At that point you should just... fix the bug.
“Let’s monitor in real time for whether any possible combination of inputs could produce a technically valid but undesirable state” doesn’t sound any less complicated or more effective than finding bugs and fixing them.
And yet you still see that approach in the wild. In the game destiny 2, there are a slew of bugs which seem to result in failed assertions, at which point your character suddenly dies. The message which describes what killed you will read "Killed by the architects" as a catch-all. The game has been under development for years and years but somehow the players (and bungie) have come to accept random dying due to physics and netcode bugs. I'll say it's better than an outright crash, but not by a lot.
Huh. It still seems there’s a meaningful difference between “if we’re in a bad state, kill the character instead of trying to recover” and “see a bad state coming in advance and avoid it”, which is what parent proposed.
The Destiny version doesn’t require understanding the bug, only recognizing after the fact that the player has, say, clipped out of bounds. Doesn’t matter how you got there. That sounds like a decent compromise for a pvp game where preventing exploits is very important.
But being able to extrapolate that the current state will lead to a bad state implies that you already understand the bug and could, you know, fix it.
Yes, you're right. My example was not quite the same. Detection of errant state is sort of the starting point, knowing preconditions is a step further in debugging.
Well stated argument! I always wondered why your car sometimes launched to the sky in Stunts, from 1990.
Yes, you could have for example energy limiters and total momentum checks in your algorithms. Energy can not be added in a collision. In a collision between two finite mass objects, total momentum is preserved (you can't use this with collisions with the ground). Maybe games already do this?
You could also just fudge the equations to avoid singularities, like always add +1 to the divider. This could probably cause other problems though.