Sanable Engine

A proof-of-concept framework built around plugins and seamless hot-reloading in C++, with an extensive reflection and type erasure system. Cross-platform thanks to SDL, including building to web using Emscripten.

sanable: adjective (obsolete)

Capable of being healed or cured.

Merriam-Webster English Dictionary

The hot-reload feature the engine is named for is made possible by memory pools and a custom, detailed reflection system in the style of C#. Pooling also enables cache-friendly update and render calls. I’ve gradually grafted in systems from my other projects, such as an asset management system similar to Unity’s Addressables.

Memory pooling makes almost every advanced feature of this project possible. The hot-reload system wouldn’t be possible at all without a way to track all existing objects, which memory pooling handily provides. Plugins are written in pure C++ and compile to DLLs (or .so on linux/web), which makes the problem more difficult. When unloading and reloading a DLL, addresses may change and objects may resize, invalidating any pointers.

Solving hot-reloading proved quite challenging and required me to research memory layouts, compiler design, and code generation. I’ve split it into several separate posts to keep this page as a brief overview:

Components inherit interfaces to mark themselves as receivers for render and update calls. While memory pools already keep the data cache-friendly, Sanable also optimizes code for the CPU cache by batching calls per-class. For example, all RectangleColliders might be told to update, then all PlayerControllers, regardless of initialization order. This is made possible by the reflection system originally built for hot reloading.

Sanable started as a class final project, but it has since evolved into something much more sophisticated. This precursor included a number of features I am still working to graft. It had a logging system with timestamps and color coded log levels for easier debugging, an input system supporting polling and two kinds of push architectures, and a similar resource streaming system. Here are a couple of field tests:

Both the powerups and the snake body segments are treated as their own Unit. Tilemap can be edited through image editing tools.
Dynamic resource loading and unloading is logged to the console. Audio takes a while to load, so it is set to always stay loaded.