There is No "Right Way"
After a conversation with @gravislizard on twitter, I got thinking about a particularly common hang-up that a lot of developers from all walks of life struggle with: the Right Way to implement a particular feature.
Yes, this is another "everything is a trade-off" article, but I wanted to crystallise some thoughts I had as they apply to gamedev. I'm taking a more programming-focussed point of view because I think programmers struggle with this the most, but this applies to design, and art, and even marketing choices as well.
The title is, of course, hyperbole 😅
There might be a Right Way to implement a certain feature in a given context, but there is usually not in the general case... and boy do people love to fixate on the general case.
This is really hard to accept for most gamedevs, new and old.
- For new gamedevs, there are many opinions touted as fact and patterns touted as rules in books, blog posts, youtube tutorials, and school courses. If there are no globally true set of principles to code by, how do any of those books get written?
- For more experienced gamedevs, sometimes it's as simple as "There must be a Right Way, because I've sure seen the Wrong Way in practice". We've also had more time to accumulate biases and misconceptions out in the weeds.
However, the advice on how to write clean/fast/safe code from that clever programmer is still just advice - guidelines, rather than concrete rules. That terrible broadphase implementation you saw in a legacy codebase was still just one implementation, and may even have been the Right Way at some point in that project's lifecycle, or at least seemed like it.
To give a more concrete example, let use game physics and collision.
I think it's a good example because there's super-obvious trade-offs involved, that most folks can understand. Also, I've already written about it in my NotGDC'17 article on Bucket Grids 😉
However - this doesn't just apply to physics! This applies to everything. The Right Way to go ahead is going to depend on what you need, how much time you have, and your level of experience.
To help see how this might apply elsewhere, I'll also provide an analogy to other areas of gamedev for each situation.
Match 3, ASCII Roguelike, Text Adventure
For many games, you don't need a physics engine at all. Implementing some basic equations of motion for cool particle effects might be a nice thing to add when juicing up the game, but maybe collision can be ignored completely.
- No work
- No physics
- No Networking
- No DRM
- No Localisation
- No Control Bindings
- Final Destination
Indie Top Down RPG or Platformer
You can often get away with O(N²) loops over the objects you to collide and the constraints to maintain, and some basic maths to resolve collisions after the fact.
Many gamejam games get away with this, as do many simpler indie titles, and even several older AAA titles with fewer concurrently active objects.
- Pretty easy to get started
- Room to optimise after-the-fact
- Won't scale to big simulations without more work
- Load all sound effects + textures once at startup
- Client-authority send-everything networking
- Decoration objects as "fully fledged entities"
This will often be referred to as "The Wrong Way" to do something in some circles. While you should be mindful of the choice you're making, pragmatic minimalism goes a long way in many situations. There's a lot to be said for getting it done.
Bigger Metroidvania, Shoot Em Up
For more complicated situations (lots of objects, big levels, bullet hell), you'll probably want to optimise. This might look like a bucket grid or quadtree, but might also be as simple as maintaining active/inactive lists in some cases, or only colliding objects in the active "room".
- Faster to execute for non-pathological cases
- Can be added to the simple case if/when needed
- More engineering work
- Can become more complicated to interact with elsewhere
- Often some memory overhead (Compute/Memory trade-off)
- Occlusion culling and batching for a rendering system
- Streaming assets in a big game
- Delta compression and influence tracking as part of a networking stack
You want to be sure you actually need to optimise though. Common physics optimisations are sometimes slower in the easy case - but worse than that, there's simply no point optimising collision between a handful of objects
Complex Requirements, No Expert On Team
For many games large and small, integrating an off-the-shelf physics solution will be the way to go. Box2d, Physx, Bullet, Havok... they've all been used in commercial games to great effect. Stuff bumps against other stuff. Scales well to complex worlds. Can handle detailed constraints.
- Very robust
- Does everything "clever" for you
- Someone else's job to make sure the maths is right
- Very high bang to buck ratio
- Added Dependency
- Does take some work to learn about and integrate
- Can cause platform lock-in down the line if you're not careful
- Often less flexible/customisable
- "Foundation" Libraries: Image loading, sound, graphics
- Networking libraries: ENet, Raknet
- Any other middleware.
The takeaway here: if a library can do it better, faster, and it matches your requirements, you should probably use that library. Just be careful that it actually does match your requirements, or you'll be in trouble down the line.
Niche Requirements, But You're An Expert
You have a complicated requirement, like a water sim with pressure support that flows around in your 2d tilemap world, causing cool particle splashes and knocking objects around.
...But wait, there's no off-the-shelf solution available for that!
Such situations usually require a bespoke, often complex solution - perhaps with some judiciously applied cheating for good measure. If your game world is huge (think dwarf fortress or factorio) or has something special like a dedicated fluid sim, power grid, collapse system, or real time deformation, this will be you.
You'll have to find the best way to forge ahead on your own.
- Can do whatever fancy thing you need it to!
- Big time/money cost
- Risk of failure
- Custom rendering systems
- Character customisation systems
- Procedural generation (levels, dialogue, items, characters)
Niche Requirements, But You're NOT An Expert
(or you're short on time)
You can always fake it 😉
Be careful going into situations that you know/expect not to fully understand, or where you don't think there's enough time left to do the mechanic justice. This is often where those systems no-one wants to touch 3 years down the line are born...
However, it's also where a lot of "special sauce" comes from. Going outside your comfort zone can be hugely rewarding.
Just make sure people aren't going to get hurt as a result! This applies a lot more to games than to systems handling sensitive data or where safety is at stake!
The process of becoming a "Good Gamedev" isn't an exercise in rote-learning every algorithm, data structure, trick, hack, and shortcut used in production. You'll pick a lot of that stuff up as you go, and you can look up almost anything these days if you're stuck.
It's having the understanding to predict which choices will matter, the confidence to make a choice and stick with it, the ability to do the hard work when the situation calls for it, and the humility to learn from the bad choices you inevitably make along the way.