I have not posted any content in some time, as I promised myself I would, but that does not mean I have not been working on the game. Sure, I had a kid, and there’s this whole pandemic thing I’m sure you’ve at least heard about in passing conversation, but I still steal away a few minutes here and there to work on fun stuff. It’s my way of keeping the mental knives sharp.
It is because of this strategic and economical time slicing that I chose to work on the game instead of writing about working on the game. It is really a shame (*cough* high opinion much? *cough*). In all seriousness, I managed to shoehorn several good patterns into Unity, despite it’s best efforts to foil me. More content on how to do this would be great for the community, as good design does not seem to be a topic covered (or adhered to) in any Unity tutorials.
Here’s a list of some cool stuff I pulled off:
- Dependency injection with Zenject – this was huge, the most important piece to make work. Before Zenject, testing was so difficult I did not bother. This was acceptable during the ‘learn the ropes’ phase, but testing is necessary for any real software project, game or not.
- Testing – Testing is incredibly important, and Unity really makes it difficult to test certain things
- Loading assets and Addressables – I really wish I’d seen that AssetBundles had been replaced before I implemented them. Replacing them with Addressables was an interesting challenge, as Addressable apis are all async, which throws a wrench into things when all your asset loading code is synchronous. This revealed several massive shortcomings in Unity’s workflow, in my opinion, which required interesting solutions.
- Shadergraph – building shaders with Unity’s visual editor is super cool. I achieved some awesome visual effects I doubt I would have figured out with code alone.
- Pixel level particle effects with PixelSurface – really awesome pixel particle effects. PixelSurface allows me to turn any texture into a particle system.
- Message bus with Zenject signals – A message bus is a great pattern for notifying other systems when something important happens, in my case, notifying the UI of stuff happening in the game world.
- Factories – replacing GameObject instantiation with factories. This eases testing and simplifies game logic when dealing with complex GameObjects.
- Procedural world generation – this is currently the most complex piece of the game. I have refactored it several times, and it is still a bit unwieldy, but it gets better with every iteration.
- Deterministic randomness – RNG and jitter grids.
- Perlin noise in terrain generation.
- Reflection trickery – I use reflection mainly to enable the open / closed principle to reduce overhead in adding new game assets.
- Saving the world (to disk) – Serializing / deserializing the game state to data is an interesting problem to solve with ever changing game assets being added to the game. Made even more interesting in a world that can be generated infinitely.
And that’s just the crap I remember. I’ll be getting to producing some videos