Slow Rush Studios logo,
    depicting an apprehensive-looking snail rushing forward

Slow Rush Studios

◂  Level Progression
News index
Target Practice  ▸

Architectural Questions

Contents

The good thing about building an engine just for your game is that it lets your game do things other games can't (and it's often fun - or at least educational).

The bad thing about building an engine just for your game is that if you want to Frobber something, you first have to build Frobbering into your engine.

The ugly thing about building an engine just for your game is that building an engine means making a lot of choices (what can even be Frobbered?). And - especially when you're coming from a non-game-development background - it can be hard to tell whether you're making the right choices.

This update is more programming-oriented than usual, so if that isn't your jam then feel free to skip. No gameplay-related news here. Back to our regular update style next week! (hopefully)

The Questions

I was pretty happy with my speed of development until about 6 weeks ago.

6 weeks ago is also when I shifted focus: instead of figuring out how atoms and moving bodies should work, I started implementing a bunch of kinda-boring stuff every game needs - like loading levels.

Initially the slow down was because those things needed under-the-hood game-engine-y bits and pieces (like making asset loading work for the web build).

But then those slowdowns made me wonder whether writing an engine was a sane choice in the first place: after all, standard advice is "don't write an engine", and a good chunk of what I've spent time on is "free" in other engines - everything except atoms and their interaction with rigid bodies, really.

The Crisis of Faith

I'm writing the game/engine in Rust, and 3 weeks ago LogLog Games published Leaving Rust gamedev after 3 years.

I have experienced all of the problems mentioned by the author, but I had assumed workarounds existed for them or that they were manageable.

That nagging back of my mind question about writing an engine suddenly became very front-of-mind: did I make the wrong choice in choosing Rust? Am I insane for writing my own engine?

On Choosing Rust

I chose Rust (and a custom engine) because of three requirements:

  1. Performance: I need fast performance for the atom simulation - which means using Rust, C, C++ or (maybe) HPC#.
  2. Determinism: when the game runs, I want each step of the game's simulation to result in identical output, no matter what computer it's running on.
  3. Learning: implementing game-engine-things from scratch will teach me more about how games work under the hood, so I can make better games.

But! I missed the key requirement for making a fun & engaging (vs technically-correct) game:

  1. Iteration speed: be able to try game ideas quickly to find the good ones and throw out the bad ones.

And as LogLog Games points out (at length), iteration speed in Rust kinda sucks:

The Search for Answers

Can I meet all 4 requirements? Well, the "learning game (engine) dev" requirement conflicts with iterating quickly, so: no.

But I can give up some "learning" for some "iteration speed".

And so (here I condense 3 weeks of research & investigation into a few sentences) a reasonable balance of the 4 requirements is to still write the core game simulation in Rust (for performance and determinism), but use an existing game engine/framework to power the undifferentiated game-engine pieces (gaining back some iteration speed): things like audio, rendering, input handling, windowing, etc.

The 3 major game engine options are (in order of "most mature" to "easiest to integrate Rust") Unity, Godot, and Bevy - so I'm leaning towards Godot as a reasonable balance.

I haven't actually done that integration yet, but I feel a lot better about having that plan in place.

Better Iteration in Rust

Some of my investigation into bending Rust towards faster iteration times also helped:

And, I reorganized the game logic to use an Entity Component System (called hecs). For the coders: basically instead of having big objects with functions attached, you have a list of numbers (entities) and each number has one or more chunks of data ("components") that can be accessed; you can't get at the data except by writing functions ("systems") which read data from the world using using those entity integers or asking the world for the records for all entities having (or not having) certain records.

Anyway, Entity Component Systems are often pushed for performance benefits, but I mainly adopted one because it sticks a lot of your game's state into one place, and that's more convenient when you want to hack something together. (I was already composing objects together to get behaviors, but that composition did get a bit nicer too.)

One thing I haven't tried yet is getting actual code hot-reloading working - maybe next week.

Gameplay-identical web build‎

This week's playable build should be exactly the same as last week's - at least as far as you can tell.

Click to focus, then play with keyboard and mouse. No mobile support! Give feedback.

Well, maybe in the course of my invisible work I snuck in a bug or two - do let me know if you find any!


◂  Level Progression
News index
Target Practice  ▸