The Buttr Framework

Backend. Buffer.
Simulation.

Dependency injection in clear C#, combined with DOTS simulation. Two systems running on different clocks, with different rules, both communicating. Buttr is the stack that connects them. And its CoreCLR compatible.

Preface

I'm going to make a quick note here as Buttr thus far has only been Dependency Injection (DI). This page is a sample of the full Buttr stack. You do not have to use the full stack. Use only the DI if you don't care about DOTS. I won't lie you will need to install the full stack to setup the DOTs Buffer. The documentation that follows will outline each system individually. They're all packaged separately so you can pull in only what you need. Have fun.



Where it came from

Buttr started as a frustration with how Unity wants you to build. The default workflow - scripts reaching into scripts, one manager that quietly knows about everything. It runs fine, but it always felt structurally wrong. It's like fighting the engine to hold onto any real architecture. Monobehaviours felt like a bottleneck and heavy. A few years of chasing that down through various design patterns and other languages later, this is the shape that finally felt right. The rest of this page is how it works, explained through one small sample game that runs on it.

The problem

Unity gives you two worlds and they don't talk.

Object-oriented
The Backend

Services, saves, storefronts, UI. It allocates freely. It holds references. It runs when something happens. Comfortable, productive, let's make it event-driven.

Data-oriented
The simulation

Burst-compiled jobs over raw data which runs every tick across multiple threads. A managed reference here won't compile. Why use it? For speed of course.

Most projects end being built one way. Either the simulation is built entirely in managed code, or the whole backend gets rewritten into DOTS. The point of Buttr is to say why can't we use both? Two layers and an explicit transport between them makes this possible.

The stack

Backend. Buffer. Simulation. The Buffer relaying events between either end.

The Backend never reaches into the simulation. The simulation never holds a managed reference. Anything that crosses travels through the Buffer as a small envelope, at a set point in the frame. When a payload is too big to fit inline, it rides alongside in a side arena the envelope points into.

Layer 1 · event-driven
Backend
Buttr DI · managed, object-oriented
  • Services & repositories
  • Persistence & save/load
  • Platform / web / Steam SDKs
  • UI logic
Layer 2 · once per tick
Buffer
Buttr.Dots · Burst-native transport
  • Double-buffered queues + arenas
  • Blittable envelopes only
  • Signal Domains & codecs
  • Drain systems
Layer 3 · tick-driven
Simulation
DOTS / ECS · per-project
  • Systems, jobs, Burst
  • Entities & components
  • No managed references
  • The hot loop stays hot
SimCommand · Backend to sim, drained at the start of the tick. Here: ApplyUpgrade
SimSignal · sim to Backend, drained after simulation. Here: EnemyKilled, WaveCleared

The point here is Buttr provides a full stack for building large scale simulations. The best part; if backend code is built right it can become core packages that can be shared between projects. Then the entire focus of building a game only needs to be on the simulation. The DI of Backend Buttr makes this possible.

The worked example

Meet Wave Survivor.

Every snippet on this page comes from one small worked example we built called Wave Survivor. It's simple, straight to the point, and compiles/runs on Buttr's real APIs. In a survivor game thousands of enemies want you dead, the textbook case for Burst; its XP, inventory and progression stay ordinary C#, which is exactly what the Backend is for.

1 · Simulation
An enemy dies
2 · Buffer
EnemyKilled signal
3 · Backend
XP accrues → level up
4 · Backend
Player earns upgrade
5 · Buffer
ApplyUpgrade command
6 · Simulation
Sim applies the upgrade

Each layer gets its own tab up top. Follow the beat through them in order, or jump straight to the one you came for.