Dev Log
16 September 2026
- Remove EntityRegistry from the simulation in favour of stable IDs and authoritative agent SOAs
- Migrate high-value SOAs to single-allocation storage and add identity indexes
- Add high-count fighter Tracy benchmarks and improve worktree and benchmark documentation
15 September 2026
- Refactor simulation ticks into preparation, thinking, and action phases
- Tighten native simulation APIs, CMake layout, and test observation boundaries
- Coordinate builds and editor readers through a shared engine gate
- Harden jobserver lifecycle, IPC, and queued-work handling
14 September 2026
- Add a resilient per-user jobserver for CMake workflows across worktrees
- Add native simulation runners, benchmark comparison tools, and packaging workflows
- Strengthen generated-code coverage and native CMake presets
13 September 2026
- Migrate core combat simulation, levels, and tests into native C++ libraries
- Adopt pinned native dependencies, C++23, stronger warnings, and hierarchical CMake workflows
- Add Tracy profiling and improve optimized native build settings
12 September 2026
- Move core simulation storage, collision, and query code into native libraries
- Add production celestial backdrops, GPU starfield refinements, and plasma targeting visuals
- Add S7 level import/export, generated materials, collision damage, and native benchmark workflows
11 September 2026
- Add native material synthesis, image generation, and game-memory libraries
- Move single-allocation SOA generation to structured C++ AST nodes
- Add frame-local simulation scratch storage and coordinate Unreal builds across worktrees
10 September 2026
- Simplify generated single-allocation SOA layouts and add telemetry sparse tables
- Add the procedural SandboxMesh editor mode, assembly tools, and mesh lab
- Improve player flight trim controls and code readability
9 September 2026
- Add range-gated target glow and a GPU glow lab
- Separate simulation from presentation modules
- Harden and benchmark generated single-allocation SOA storage
8 September 2026
- Refactor player-controller, HUD, and modal lifecycles
- Harden control-chord capture and input binding feedback
- Simplify registry and level-simulation lifecycle management
7 September 2026
- Add scalable fleet benchmark levels and battle-performance telemetry
- Improve fighter avoidance, spawn-clearance tools, and observer controls
- Add configurable control profiles and a production tactical radar
6 September 2026
- Add a telemetry dashboard, battle reports, and low-overhead per-level telemetry
- Refine the Hive battle HUD, objective overlays, soft targeting, and analytic sparks
- Expand mission browser, save archive, controls, and benchmark tooling
5 September 2026
- Add generated SIMD kernels, benchmark workflows, and kernel coverage
- Build out Hive-themed menus, settings, campaigns, and pause statistics
- Add snapshot-based, triple-buffered SandboxISMC rendering with automation coverage
- Introduce the experimental S-expression Slate DSL
4 September 2026
- Move combat gameplay from actors into the simulation and retire legacy weapons
- Route targeting, collision, and line-of-sight through the uniform grid
- Add scripted missions, objectives, progression summaries, and CommonUI menus
3 September 2026
- Harden collision traces, grid boundaries, and authored-level loading
- Add GPU-generated nebula density volumes and playerless level cameras
2 September 2026
- Add line-trace tests and initial collision hit effects
- Add script-driven level loading and nebula shader experiments
31 August 2026
- Add native level definitions and a configurable collision grid
- Begin line-trace support and collision-shape extraction
- Add configurable continuous Niagara effects
30 August 2026
- Add the uniform-grid collision foundation and automated coverage
- Expand the GPU starfield and Niagara experiment tooling
- Add save-profile viewing and embedded S7/Lua language experiments
29 August 2026
- Add shockwave, signed-distance, and normal-map image generation
28 August 2026
- Add the interactive Sandbox Image Lab with procedural noise generators
- Move the code generator to C++ and introduce a typed AST pipeline
- Add a main menu, shader experiments, and unified level configuration
27 August 2026
- Complete the SandboxShaders playground with 3D radar and Niagara experiments
- Add frame-local arrays and richer battle telemetry
- Rework player controller input contexts
25 August 2026
- Add an RDG heatmap widget and UI showcase
- Expand SandboxCore and level-test coverage
- Reduce scenario lifecycle boilerplate in tests
24 August 2026
- Add radar, chart, histogram, scatter, and heatmap UI widgets
- Add pausing, telemetry, mission kill requirements, and a game subsystem
- Improve scripted-level selection, persistence, and test setup
23 August 2026
- Add graph widgets and richer time-series data
- Make test levels and orchestrator state reliably reusable between runs
- Add PowerShell developer commands, allocator coverage, and editor-process reuse for tests
22 August 2026
- Add blocker spawning and line-of-sight coverage
- Add CMake workflows for tests, benchmarks, project generation, and asset resaving
- Move mission management out of Blueprint and improve build tooling
21 August 2026
- Move SpaceGame code and content into plugins
- Add generated orchestrator phase facades
- Retire the obsolete ShooterGame and SpaceGameContent layouts
20 August 2026
- Add generated lambda member functions
- Use integral target biasing in fighter targeting
19 August 2026
- Add SOA entity handles and generated vector operations
- Improve code-generator support for loop bounds and trailing return types
18 August 2026
- Refine fixed-array storage and expand its test coverage
- Remove the registry Blueprint interface
17 August 2026
- Extend fixed-array and view APIs with coverage and debugger support
- Speed up turret lasers
- Add phased actor spawning callbacks for presentation setup
16 August 2026
- Add allocator support for large Windows allocations
- Expand spatial queries with line-of-sight checks and turret proxy configuration
- Improve generated entity storage, SOA copying, and sorting
15 August 2026
- Expand generated SOA types, views, row operations, and sorting support
- Move spatial-query hit resolution into SandboxCore and remove per-query allocations
- Improve fighter standby simulation coverage and time-series test sampling
- Run code generation as part of the build
13 August 2026
- Store spinner entity data locally and refresh it through the simulation
- Add tick-driven timers and strengthen entity-handle cleanup checks
11 August 2025
- Make tests use
FString::Format - Reorganise test string handling to reduce allocations
- Add
TestDisplayTraits<T>to automatically handle formatting withFString::Format
- Add
- Make separate tick loop for HUD updates
- The HUD should tick in real time and be unaffected by the simulation speed
10 August 2025
- Pull HUD manager tick out of the simulation loop
- Add
TestEqualityTraits<T>to centralise testing equality logic
9 August 2025
- Create function to generate widget blueprints with the C++ widgets already bound
- Move the HUD manager from the player controller into the orchestrator
- General improvements to testing system
- Fix bug with capital ship kills being broadcast every tick leading to scores increasing constantly
- Add optional health to capital ship proxy so they can be individually set
- Minor bug fixes
- Allow proxy actors to have a name in testing contexts
- Add widget for kills by each team
8 August 2025
- Remove lives widget
- Remove gold rings widget
- Use polling for HUD updates instead of delegates
7 August 2025
- Add player ship destruction
- Make lasers inherit shooter velocity
- Add
FPeriodicCountdownTimers, float based countdown timers with an array of periods - Add a UMG widget to display entity counts
- Create mission status UMG widget
- Add
TPeriodicTickCountdown, an integer based counter that contains a period to reset to when each timer is reset - Move HUD code out of the player controller and into a new
FHUDManager
6 August 2025
- Change some internal functions to templates
- Add hysteresis to fighter positioning instead of always being at 50% of the laserâs max distance
- Make attack reposition checks periodic
- Make
FTickCountdowna template so you can use different int counter types - Add test for fighter LOS position adjustment
- Make fighters reposition when they donât have LOS and theyâre not moving to a new location
- Add int/float biases to each fighter to add some deterministic ârandomnessâ to their choices
- Make the mission manager use fixed ticks
- Make the simulation orchestrator handle destroying proxy actors
- Decouple the mission manager from the player
- Fix player ship aim offset
5 August 2025
Trying to get tests working. Looking into new data visualisation strategies.
- Add tests for fighters intercepting a capital ship
- Fixed bug with fighter indexing when capitals were queuing orders
- Added test result exporting to data assets/tables/float curves
- Add
FTickCountdown, a tick-based timer - Add
SimulationClockInterface, a limited way of getting simulation time info from the simulation orchestrator - Add data assets to bundle data like actor configs
- Add tests for the simulation orchestrator
- Support simulation pausing
- Make fighter enemy scanning periodic
- Moved some code into the
SandboxCoreplugin and changed the tests from automation tests to low-level Catch2 tests - Clamp fighter move distances to prevent overshoot
- Add some variadic helpers for
nullptrand size checks in my loop kernel functions
4 August 2025
- Use sockets for fighter firing offsets instead of actor components
- Make fighters and capital ships much larger
- The fighters are much more readable in battle now
- Reorganised a bunch of internal assets
- Implemented fixed tick rate in main orchestrator
- Allow variable simulation speeds (Tests now run at 20x speed)
- Visual updates are decoupled from the simulation
- Use
NativePreConstructforUValueWidgetpreviews - Allow fighters to intercept nearby enemies when moving to their objectives
- Add
TimeSeriesDataclass for sampling{time, value}pairs from tests for easy post processing - Add
FTestTimeline, a container of{time, fn}for queueing test simulation events
3 August 2025
Add team-based colours to laser hits for combat readability. General internal improvements to logging and internal data structures.
2 August 2025
Tore the barrel roll code out. RIP Starfox clone.
Made a UMG widget to display 2D vectors. This will be needed for future ideas where we could control ship systems with a sample and hold system using the analog stick.
Sample and hold is in. I now have a weird control scheme. XY direction is chosen by holding R1 and then selecting a direction on the analog stick. This is locked when when you release R1.
Then the left analog stick is used for rolling and for Z motion. The right stick is always for pitch and yaw.
Itâs an odd scheme. You need to continually adjust your motion. It doesnât feel bad.
Iâm a bit tired with games feeling a bit samey. Iâd like to experiment with something that maybe isnât good or is sub-optimal but we see if anything interesting comes from the constraints.
1 August 2025
Make a new TimeSeriesData class.
This makes it easy to sample data in CQ tests.
I then made a single cast delegate for the tick end in the orchestrator for testing.
We set up the test, run it for N seconds, and then weâve a ton of data that we can post process in one go. Pretty much how weâd do analog IC simulations.
Added some Catch2 based benchmarks with a CLI arg to tune the size.
Moving away from a Starfox 64 style control scheme to a more traditional twin stick shooter.
Fighters now lead their shots and are much more deadly. The Starfox style movement couldnât cut it. Weâve now got movement in the YZ axes for dodging.
Screenshots
28 July 2025
Implemented fighters stopping at an attack radius around the target.
26 July 2025
Storing entity radii in the registry for simple volume querying. Fighters now do a LOS check before firing. It doesnât solve all cases of friendly fire but itâs better than nothing.
Hours of pain due to my tests. I tried to be simple and not introduce a direct damage system for the tests. When I changed how my ships flew, they began to overlap during the tests. When my test driver did some scripted kills, it did damage to a location which ended up killing the wrong entities. It was hard to debug.
Iâve added a second direct damage path in parallel with the collision-based damage path.
25 July 2025
Created a SandboxNative module for game code that doesnât require the engine or editor.
This allows me to make SandboxNativeTests which uses Catch2 based low-level tests.
Set individualised spawn timers for capital ships.
Capital ship proxies can override the actor configâs initial spawn delay and spawn cooldown.
Refactored the CQ test code to remove repetition in test setup.
Built a simple test to evaluate the attack task for fighters.
Cleaned up some batch actor code.
Moved non-USTRUCT structs into namespaces so they could have shorter names.
21 July 2025
Reordered the spawn phase for capital ship fighters.
Originally the timeline was:
- Capital ships spawn fighters
- Capital ships refresh their view of the fighters
- Capital ships send orders to fighters (these take effect immediately)
- Sort internal fighter data by their current task for easy batching
- (general game simulation)
- Fighters prune dead entities if any were killed
- Tick end
This involves changes to the fightersâ data layout three times in the tick (spawn, sort, prune). It was messy and the dataâs representation was less stable than I wanted.
Capitals now queue spawn requests which are committed at the end of the frame, right after the kills. We now have two layout changes instead of one. Capitals now see a stable view of the fighters during their decision phase.
I intend to make the orders also use a queue system. I can either delay to the tick end or the start of the next tick. Either way, all the state changes will be localised to one tick boundary.
My check() calls CQ tests are proving their worth.
The transition to tick-end spawns was pretty simple.
Issues with the data were caught immediately by the check() calls and the tests confirmed the resulting gameplay was unchanged.
19 July 2025
A day of pain with debugging the fighter tasks system. The issue was in the tests. My mistake was to use indexing when itâs not really stable anymore. I need to work exclusively with handles.
18 July 2025
More work on the fighter state machine. The challenge is keeping them all contiguous without multiple sorts. In the end a brute force check was fine. I use SOA layouts and with 3600 fighters, the check only took 1.7 Îźs according to Unreal Insights (including the 100ns profiling overhead).
The rest of the day was pain. Trying to fix issues with syncing the state.
15 July 2025
Worked on the fighter state machine. For now weâll have three states:
- Idle
- Move to location
- Attack
Each state is a superset of the other. To simplify the logic, Iâve let the fighters move in a 6DOF Descent-like style. This skips having to put in attack runs. The fighters can just stop dead at their targets and shoot at them if no one else is around. Fighters will have an attack band within which they shoot. If theyâre too close, we can just make them reverse.
11 July 2025
- Finished off the work to unify target handling in the editor.
- Fighters are now reassigned to a new capital ship when their parent dies
Unified target handling
The proxy classes are being extended to hold this interface.
class ITestEntity {
GENERATED_BODY()
public:
virtual auto get_entity_handle() const noexcept -> FRegistryEntityHandle = 0;
};
Itâs used to allow arbitrary targeting in the editor.
5 July 2025
- Merged entity registry update function and the death update function
- Have capital ships not spawn fighters if they have no target
Fought for hours with Unrealâs functional testing framework. For whatever reason, itâs the most unstable system when I use it. The most recent issue was:
- The level would load
- The actors were there (or some were)
- The test actor kept reading back zeros and null data from my entity registry
- Breakpoints werenât hitting for the non-test actor
It was like the actors werenât being copied over to the new level properly. I discovered CQ Tests which allow level loading. They appear to work.
4 July 2025
Set up a hub page for Blender. I donât use it often enough to remember things so this will be very useful.
Game design
- Added a fire rate toggle
- Fighters now react to being shot and fight back
- Made a new 3D model for the fighters
- Fighters and capital ships have mask textures and glow with the team colours
- Fighters and capital ships choose new targets when the original target dies
Fire rate
Iâd like to explore how different rates feel.
- Single shot
- Burst (existing mode)
- Auto fire
I think I will need some kind of heat system to dissuade holding autofire down.
Screenshots