Blog 3.0 I make games.
2023 Retrospective
Ephemeris
In my last retrospective I talked about starting serious work on Ephemeris. Ephemeris is an orbital combat simulator game, with near future technology, attempting to be as realistic as possible.
I started off the year experimenting with an n-body integrator in Unity ECS. Eventually settling on using an RKF45F integrator which allows the timestep to change constantly, doing the least computation required to satisfy your accuracy requirements. You can read more about the integrator in Ephemeris Notes.
After that I started working on… drawing lines! This might sound trivial, but there’s actually a huge amount of complexity in drawing lines and it’s critically important for a game like Ephemeris which will represent almost all game state as lines and labels on those lines! These lines need to be fast (there’s a lot of them), fixed width in screen space (they can’t be in world space, scale is too big in space), not suffering from aliasing (it looks awful), capable of being marked (e.g. points of interest or regions of interest). I experimented with various approaches to line rendering to solve all these problems: GPU rendering from a compute buffer, building meshes on CPU, signed distance fields for grids and pure GPU pixel perfect bezier curve rendering.
Cylon Game Jam
This year we ran another Cylon community gamejam. This year we all suggested a topic and then voted on them to generate a ranked list of themes. Every game required the top theme and could freely pick at least one other from the list:
- 50: Exploration
- 49: Time
- 47: Sacrifice
- 46: Once more, with feeling
- 45: Navigation
- 41: Unlikely Combinations
- 39: Computers/Circuitry
- 36: Don’t Stop Moving
- 15: Musical
As usual I massively overdid it and picked the top 4 themes and also decided to make the game a multiplayer game! Ephemeris is a multiplayer game, so this seemed like a good opportunity to build a complete multiplayer game end-to-end.
The game is a twin stick, top down, co-operative, dungeon crawler. The twist on the co-operative dungeon crawler theme is that every time the party dies it rewinds back to the start and you respawn. At the same time copies of yourself replay all of your previous runs at the same time! This means you have to co-operative with yourself to solve various puzzles in the dungeon.
A game like this requires a huge amount of work creating the animation state machine, controlling movement (walk, run, dodge roll, dash), attacks (sword slash, big sword slash, sword jab, fire bow, spear jab etc), defence (shield block) and reactions (hit, big hit, stunned, death) and all of the various transitions between these states. Here’s that in action:
I’ve never used the animation state machine in any of my games before. My games are usually much more like “simulations” that you can interact with, and an animation state machine is not required for that. It was great to learn this tool.
Much of the game ended up becoming driven by this state machine, player inputs would simply trigger animations and if I wanted to adjust the gameplay effect of that (e.g. make a sword slash happen a bit faster) I could just adjust the state machine. I’m sure this is how many games are made, but it’s new for me!
Overall I’m very happy with how the game turned out. The concept is simple, but very fun to play with and people had a lot of fun playing the game in different ways during the demos. For example some people played it solo, some people just explored the dungeon, some people kept killing the same enemies over and over making the fight more and more of a mess, some people tried to speed run it (shortest overall length) and others tried to speed run it (shortest time from final spawn to exiting the dungeon). I think it’s a great sign that people enjoyed the game enough to do all that! I think the concept could be developed into something worth selling, but this kind of game requires a lot of art assets so it’s not something I’m likely to do.
If you would like to try the game out it is available to download here. If you want to play multiplayer you will have to open port 7777 on the host (it is possible to play solo, since you can always co-operate with yourself from another timeline when necessary).
By the way one of the rooms in the game will slow performance to a crawl, if you find it you’ll have to start a new run since performance will be ruined on all future runs too! Gamejam quality software ;)
Obsidian
Last year I started writing the Ephemeris Notes, a set of notes on all things related to Ephemeris. I found this really helpful for organising my thinking on the project, writing down scattered thoughts so they can be refined later or writing detailed articles on complex topics so that I myself can re-read them later when I’ve forgotten the details!
Inspired by that experience I started using Obsidian for general note taking this year. I haven’t fully embraced the note taking, and in fact my use of the notes has fallen off a little recently, but it’s something I’m going to keep working at in 2024.
Placeholder Software
Dissonance
This year we’ve released 4 updates for Dissonance with a number of improvements:
- Fixed an issue with resuming audio playback after the app is suspended (e.g. put into background on a phone).
- Many smaller fixes related to resuming from backgrounding (e.g. resetting various counters).
- Added a new
IAudioOutputSubscriber
interface, which makes it easy to access (and modify) to the audio Dissonance is playing. - Fixed
Amplitude
property for the local player so it measures after preprocessing (most importantly, after gain control). - Fixed spelling of
SubcribeToVoiceActivation
. Only took 6 years for someone to spot that! - Added additional metrics accessible on the server (e.g. packet loss).
- Added an “always send” room that forces audio to be sent to the server (even if no one is listening).
Wasmbox
Last year I mentioned that were were developing “Wasmbox”, a WebAssembly runtime for Unity. Wasmbox ended up developing into a very cool project that could do lots of cool tricks. A WASM file could be imported in through the Unity asset pipeline, this import process automatically applied Wizer initialisation, Binaryen optimisations (including asyncify), Wasmtime precompilation (i.e. skipping runtime JIT cost entirely), Brotli compression and auto generated C# wrapper code.
The C# wrapper code was particularly useful, it enabled us to make sure that a loaded WASM instance is not “misused”. For example a call can be made inside a job and the entire instance is unusable while the job is running (i.e. an extension of the Unity “safety system” to arbitrary WASM calls).
You might notice that this section is written in the past tense, well that’s because of the Unity shaped elephant in the room…
Unity Backstab
Back in September Unity announced a sudden and unexpected pricing change to a totally insane pricing structure based on installs. Everyone in the games industry hated this fee structure and the backlash was incredible to watch. 10 days later they announced a complete replacement of this install fee with a new policy which is much more reasonable. This was a total disaster for Unity, and we still haven’t seen all of the fallout from this decision.
At Placeholder Software we decided to rollback on developing new products (such as Wasmbox, which we have deprecated) and instead to transition to just supporting our existing projects (Dissonance is not going anywhere). This is because if they can decide to just roll out totally insane policies like the runtime fee overnight then Unity no longer seems like a safe foundation to build assets and games on.
Of course this has left me with a big decision to make: do I trust Unity long term and keep developing with Unity (which I do consider to be a good engine)? Or do I migrate to another engine and start learning from scratch again?
At the time this was happening I looked around and found three potential candidate to replace Unity:
As of right now I have not decided which engine to use, or if I should stick with Unity. However, what is clear is that I can’t learn a new engine by working on a project of such complexity as Ephemeris! This has directly led to me starting a new game…
Protologic
Back in 2021 my entry for the Cylon gamejam was Saturn’s Envy. This was a programming where you you used Yolol (the language which Cylon is all about) to program space battleships. When you had a program you could submit it to a Discord bot which would schedule battles and maintain a leaderboard of ships. This was pretty fun, and quite a few people submitted fleets, but it was always held back by the fact that Yolol is a terrible language and no one wants to build large complex software in it!
Protologic re-imagines this idea, the ships now run WASM. That means that the ships can use any language which compiles to WASM, of which there are many! If you’re interested in this the Protologic bot is currently available in Cylon, and the battle replays are available to watch online here.
This is a great project to learn new engines because the sim (running battles & generating replay files) is completely decoupled from the front end (loads replay files and displays them in a game engine). This means I can build a completely new “front end” in another engine without having to worry about the complexity of re-implementing all of the game logic. The current frontend is written in Unity (adapted directly from the gamejam submission) and I plan to write new frontends in Godot and Stride.
Open Source Projects
Wazzy
Wazzy is an implementation of the WASI spec (WebAssembly System Interface). It is written in pure C# and is designed to be easily extensible with custom implementations of parts of the spec. This was originally part of Wasmbox, but it seemed a shame to let it die, so I’ve extracted out everything except for the filesystem implementation into this open source project. This is in active use in Protologic.
Autofocus
Autofocus is a C# API client for the AUTOMATIC1111 API. It attempts to model the API in a type-safe way, preventing possible user errors. This is in active use in *Mute (my Discord bot).
LLamaSharp
LLamaSharp is a C# wrapper around llama.cpp. This is not my project! Back in July I tried to use LLamaSharp in *Mute but I quickly encountered some errors and submitted some PRs to fix them. 295 commits later and I’ve become one of the lead developers on LLamaSharp!
Interesting Stuff
Some other interesting things that I encountered in 2023 in no particular order:
- PicoVision
- WASM Languages List
- Banner of the Stars (anime)
- ChatGPT
- Obsidian
- Stride3D
- Gaussian Splatting
- rustc_codegen_clr
- interoptopus
archive
- 2023 Retrospective 30 Dec 2023
- 2022 Retrospective 01 Jan 2023
- 2021 Retrospective 30 Dec 2021
- Building An Interpreter 27 Feb 2021
- Yolol Parsing 26 Feb 2021
- Building A Toy Compiler 25 Feb 2021
- 2020 Retrospective 31 Dec 2020
- The Yard Sale 16 Sep 2020
- 2019 Retrospective 31 Dec 2019
- 2018 Retrospective 02 Jan 2019
- Lessons In Network Protocol Design Learned The Hard Way 23 Jun 2018
- Dithering About Dither 27 Mar 2018
- 2017 Retrospective 13 Jan 2018
- Unity Ongui 04 Dec 2017
- Dissonance Voip Pipeline 19 Feb 2017
- 2016 Retrospective 01 Jan 2017
- Dual Contouring In 2d 27 Dec 2016
- Procedural Generation For Dummies: Building Footprints 07 May 2016
- Procedural Generation For Dummies: Half Edge Geometry 30 Mar 2016
- Fixed Permalinks 21 Mar 2016
- Procedural Generation For Dummies: Galaxy Generation 14 Jan 2016
- 2015 Retrospective 04 Jan 2016
- Procedural Generation For Dummies: Lot Subdivision 27 Dec 2015
- Procedural Generation For Dummies 11 Dec 2015
- Procedural Generation For Dummies: Road Generation 11 Dec 2015
- Deferred Transparency 09 Oct 2015
- Xna In 2015 24 Aug 2015
- Node Machine 26 Jun 2015
- Procedural Generation Of Facades And Other Miscellania 29 May 2015
- This Path Was Made For Walking 23 Apr 2015
- Cross Chunk Navmeshes 27 Mar 2015
- Changelog 27 06 Mar 2015
- Drawing Stuff On Other Stuff With Deferred Screenspace Decals 27 Feb 2015
- Random Gibberish 22 Feb 2015
- This Wall Is Sticky 17 Feb 2015
- Changelog 25 08 Feb 2015
- 2014 Retrospective 13 Jan 2015
- Super Sonic Sound 08 Jan 2015
- Sandboxing Is Dead Long Live Sandboxing 22 Dec 2014
- Changelog 22 B 14 Dec 2014
- Changelog 22 07 Dec 2014
- Possible Interruption To Service 06 Dec 2014
- The Game Programmer Awakens (changelog 21b) 30 Nov 2014
- The Return Of The Programmer (changelog 21) 16 Nov 2014
- The Return Of The Vending Machines 26 Oct 2014
- There Are Vending Machines Everywhere 16 Oct 2014
- Changelog 20 12 Oct 2014
- Ragdolls Are Hard 05 Oct 2014
- Changelog 19 28 Sep 2014
- The Return Of The Game Programmer 21 Sep 2014
- The Ball Is Picked Back Up 17 Aug 2014
- It's Good To Be Back 03 Aug 2014
- Serious Injury 21 Jul 2014
- We Marveled At Our Own Magnificence As We Gave Birth To Ai 14 Jul 2014
- Changelog 17 06 Jul 2014
- Changelog 16 29 Jun 2014
- Happy Birthday 22 Jun 2014
- Changelog 14 15 Jun 2014
- Losing My Way 08 Jun 2014
- Wildcard 02 Jun 2014
- Changelog 13 25 May 2014
- Changelog 12 16 May 2014
- WAI NO VIDEO (Again) 11 May 2014
- Changelog 10 04 May 2014
- Changelog 9 27 Apr 2014
- Changelog 8 20 Apr 2014
- Long Overdue Style Upgrade 18 Apr 2014
- WAI NO VIDEO 13 Apr 2014
- Changelog 7 07 Apr 2014
- Changelog 6 30 Mar 2014
- Changelog 5 23 Mar 2014
- Changelog 4 16 Mar 2014
- This Is Madness! 11 Mar 2014
- Changelog 3 09 Mar 2014
- Changelog 2 02 Mar 2014
- Changelog 1 23 Feb 2014
- Changelog 0 15 Feb 2014
- Payday The Heist 2 13 Jan 2014
- 730 Days Later 01 Jan 2014
- I Just Needed A Rest 12 Nov 2013
- Splinter Cell Blacklist 27 Aug 2013
- Gruelling Homework Assignment 26 Aug 2013
- Scripting Is Dead Long Live Scripting 14 Aug 2013
- The Reports Of My Death Are Greatly Exaggerated 05 Aug 2013
- 27 Gigawatts Of Cake 11 Jun 2013
- Trees Are Well Behaved 22 May 2013
- A Brief Project Update 14 May 2013
- Finite State Machines (are Boring) 16 Apr 2013
- Pathfinding 10 Apr 2013
- Artificial Stupidity Series 08 Apr 2013
- Valve Need To Stop Reading My Mind (and Other Miscellanea) 20 Mar 2013
- Elements Of Style 26 Feb 2013
- Moving To Axmingholmesbury 23 Feb 2013
- The Future Is Steamy 08 Feb 2013
- Mathematical Trickery 22 Jan 2013
- Thinking Aloud About Release 09 Jan 2013
- Game Developers Don't Make Timetables 03 Jan 2013
- What Is Heist? 20 Dec 2012
- How Does Procedural Generation Work? 14 Dec 2012
- Why Does Heist Keep Crashing? 07 Dec 2012
- What Isn't Procedural Generation? 23 Nov 2012
- What Is Procedural Generation? 18 Nov 2012
- Procedural Generation Series 15 Nov 2012
- Packet Encoding(3) 12 Nov 2012
- Packet Encoding(2) 08 Nov 2012
- Packet Encoding 07 Nov 2012
- Deployment Hax 28 Oct 2012
- Wibbly Wobbly Pipey Wipey 24 Oct 2012
- New Release(2) 24 Oct 2012
- New Release 20 Oct 2012
- Say What? 17 Oct 2012
- Get Up And Initiate That Session 15 Oct 2012
- Topological My Dear Watson 14 Oct 2012
- Omg Wtf Multiplayer 13 Oct 2012
- Full Steam Ahead 24 Sep 2012
- You Should Check Out Greenlight 01 Sep 2012
- It's Full Of Entities 20 Aug 2012
- Persistence 06 Aug 2012
- I'll Be Back 01 Aug 2012
- Artificial Stupidity 24 Jul 2012
- Overindulgence 16 Jul 2012
- Not My Cup Of Tea 09 Jul 2012
- Artsy Stuff 02 Jul 2012
- This Was A Triumph 25 Jun 2012
- Multiplayer Release 18 Jun 2012
- Fortnightly Fun 10 Jun 2012
- New Blog 31 May 2012