Void.Engine
2.1.0
dotnet add package Void.Engine --version 2.1.0
NuGet\Install-Package Void.Engine -Version 2.1.0
<PackageReference Include="Void.Engine" Version="2.1.0" />
<PackageVersion Include="Void.Engine" Version="2.1.0" />
<PackageReference Include="Void.Engine" />
paket add Void.Engine --version 2.1.0
#r "nuget: Void.Engine, 2.1.0"
#:package Void.Engine@2.1.0
#addin nuget:?package=Void.Engine&version=2.1.0
#tool nuget:?package=Void.Engine&version=2.1.0
VOID Engine
A lightweight, modular, extensible 2D game framework for .NET.
What is VOID?
VOID Engine provides the systems most 2D games need without trying to become a giant all-in-one engine.
VOID is built around a simple idea:
Give developers solid defaults without assuming those defaults are right for every game.
Use the built-in systems as they are, extend them, replace them, or ignore the ones you do not need.
VOID deliberately stays focused on framework-level systems. Features such as full physics and full UI frameworks are left to your game or the libraries you choose.
Install
dotnet add package Void.Engine
Or install the project template:
dotnet new install Void.Templates
Then create and run a game:
dotnet new voidgame -n MyGame
cd MyGame
dotnet run
Features
| System | What It Does |
|---|---|
| Rendering | Batched sprite and primitive rendering, texture atlasing, shaders, render targets, post-processing |
| Renderer API | Public renderer-neutral contracts with a pluggable backend architecture |
| Platform | SDL3 windowing, displays, fullscreen modes, events, keyboard, mouse, and gamepads |
| Assets | Mount-based virtual file system, custom asset types, pack loading, LRU eviction |
| Audio | OpenAL playback, sound pooling, priority-based voice stealing, category volumes |
| Saving | AES-GCM encrypted saves with manifest verification |
| Pathfinding | A*, Dijkstra, BFS, and flow fields |
| Coroutines | Tweens, sequencing, delays, waits, and easing |
| Logging | Async logging with console and file sinks |
| Math | Vectors, matrices, rectangles, colors, easing, and random helpers |
| Tooling | Project templates and authenticated encrypted asset packing tools |
| LDtk | LDtk level and asset integration |
Philosophy
Extend, don't modify.
Large engines often try to solve every possible problem.
That can be useful, but it can also leave developers working around systems that do not fit their game.
At the other extreme, very low-level frameworks provide freedom but leave you rebuilding common infrastructure yourself.
VOID sits in the middle.
It provides useful defaults while exposing the places where different games may reasonably need different solutions.
The built-in implementation is not assumed to be the only implementation.
No engine fork required. No fighting hidden internals. No one-size-fits-all workflow.
VOID also aims to keep the normal path simple. Advanced systems should exist underneath the framework without making basic tasks complicated.
Performance-sensitive code is written with allocation behavior, thread safety, and hot-path cost in mind.
VOID 2.0 Rendering Architecture
VOID 2.0 no longer depends on SFML.
The built-in renderer uses Silk.NET.OpenGL, while SDL3-CS handles the platform layer and Silk.NET.OpenAL handles audio.
The OpenGL renderer is a default implementation, not the definition of VOID's rendering system.
Custom renderer backends can be selected through GameSettings:
var settings = GameSettings.Instance
.SetRenderer(() => new MyRenderer())
.Build();
Renderer plugins can implement VOID's public graphics contracts for APIs such as:
- Vulkan
- Direct3D
- Metal
- OpenGL
- custom renderers
VOID exposes native window handles through IRendererContext when a backend requires them.
Higher-level game and engine code remains renderer-neutral.
Read the Custom Renderer documentation
Extensibility
VOID provides extension points where alternate implementations make sense.
| Extension Point | Purpose |
|---|---|
IAsset |
Define custom asset types |
IMount |
Add custom asset sources |
IAtlasPacker |
Replace the texture packing algorithm |
ILogSink |
Add custom logging destinations |
IRendererBackend |
Provide another graphics backend |
IGraphicsDevice |
Implement renderer-specific GPU behavior |
IBatcher |
Add custom batching strategies |
IRenderTarget |
Provide custom render surfaces |
BaseCamera |
Build specialized camera behavior |
ContentTypeWriterReader<T> |
Support custom save-data types |
Examples:
GameSettings.Instance.SetAtlasPacker(typeof(MyAtlasPacker));
AssetManager.Instance.AddMountToStart(new CloudMount());
AssetManager.Instance.RegisterAssetType<MyAsset>(
new[] { ".myext" },
(id, data, tag) => new MyAsset(id, data, tag)
);
Logger.Instance.AddSink(new DatabaseSink());
The defaults are there when you want them.
The extension points are there when you do not.
Asset Packer
VOID includes an API and command-line tool for packaging assets into authenticated, encrypted archives.
Features include:
- AES-GCM authenticated encryption
- adaptive compression
- per-file integrity verification
- configurable chunked encryption
- streaming reads
- incremental updates
- concurrent asset loading support
Install the CLI:
dotnet tool install --global Void.Packer.CLI
Build a pack:
void-packer build -c Content/ -o Packs/
Verify it:
void-packer verify --pack GameAssets.pack
The pack system is intended to make casual extraction and unauthorized reuse more difficult while maintaining practical runtime access.
No client-side asset format can make shipped assets impossible for a determined attacker to recover.
Quick Start Without the Template
Create a normal console project and add VOID:
dotnet new console -n MyGame
cd MyGame
dotnet add package Void.Engine
Create a game class:
using Void.Engine;
public class MyGame : Game
{
public MyGame(GameSettings settings) : base(settings) { }
protected override void OnEnter() { }
protected override void OnUpdate(FrameTime frameTime) { }
protected override void OnDraw(FrameTime frameTime) { }
protected override void OnExit() { }
}
Configure and run it:
using Void.Engine;
var settings = GameSettings.Instance
.SetAppCompany("MyStudio")
.SetAppName("MyGame")
.SetWindow(1280, 720)
.Build();
using var game = new MyGame(settings);
game.Run();
Demos
FlappyBirb
A small Flappy Bird-style example demonstrating the basic VOID workflow.
Scavengers
A larger rogue-lite zombie survival example demonstrating more of the framework working together.
Supported Platforms
| Platform | Status |
|---|---|
| Windows | Supported |
| macOS | Supported |
| Linux | Supported |
VOID uses SDL3 for its platform layer. The built-in graphics backend uses OpenGL.
Requirements
- .NET 10
Runtime graphics, platform, input, and audio dependencies are provided through the engine package.
Documentation
License
MIT.
Use VOID for personal, commercial, open-source, or closed-source projects.
No royalties. No engine fees.
VOID Engine: the foundation is yours. Build the rest your way.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- NAudio.SoundFile (>= 3.0.1)
- SDL3-CS (>= 3.4.16)
- SDL3-CS.Linux (>= 3.4.16)
- SDL3-CS.MacOS (>= 3.4.16)
- SDL3-CS.Windows (>= 3.4.16)
- Silk.NET.OpenAL (>= 2.23.0)
- Silk.NET.OpenAL.Soft.Native (>= 1.23.1)
- Silk.NET.OpenGL (>= 2.23.0)
- StbImageSharp (>= 2.30.16)
- Void.Packer (>= 1.0.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
VOID Engine 2.1.0
Camera
- Cameras attached to a batcher now update automatically during rendering.
- Added protected BaseCamera.OnUpdate(FrameTime) for custom camera behavior.
- Cameras update at most once per rendered frame even when shared by multiple batchers.
- Removed the need for game code to manually update attached cameras.
- Camera timing now uses the rendered-frame timing context.
Frame Timing
- Reworked FrameTime to own and manage VOID's game-loop timing state.
- Fixed timestep updates now receive the configured fixed update interval.
- Rendering receives the actual elapsed frame time even when fixed timestep mode is enabled.
- Variable timestep mode continues to use actual elapsed frame time for both update and rendering.
- DeltaTime remains time-scale aware.
- ElapsedTime and UnscaledDeltaTime expose the current unscaled timing phase.
- TotalTime, accumulator, interpolation alpha, FPS, and slow-frame tracking remain available through FrameTime.
- Engine update systems continue to receive FrameTime rather than standalone delta values.
Coroutines
- Replaced the previous coroutine implementation with a VOID-native IEnumerator coroutine runner.
- Added nested coroutine chaining through yield return IEnumerator.
- Nested child routines can chain to arbitrary practical depth.
- Parent routines resume after their child routine completes.
- Root coroutine handles remain valid while nested children are executing.
- Stopping a root coroutine now stops and cleans up its entire active child chain.
- Coroutine cleanup disposes nested routines from the deepest child back to the root.
- Starting and stopping coroutines during a coroutine update is supported safely.
- CoroutineManager now uses FrameTime for timing.
- Numeric float, double, and int yields continue to represent scaled-time delays.
- CoroutineHandle remains an immutable readonly struct.
- Coroutine Count reports active root coroutines only.
Beacons
- BeaconHandle payload data is now exposed as a read-only view.
- BeaconHandle is safe when default initialized.
- Added Count for payload item count.
- Improved Get and TryGet payload handling.
- Beacon subscription mutation is now synchronized while keeping publishing on the existing fast multicast Action<BeaconHandle> path.
- Publishing remains synchronous and does not manually iterate subscribers.
Beacon Extensions
- Added BeaconManager.PublishDelay for delayed string and enum topic publishing.
- Delayed publishing uses the normal VOID coroutine system and scaled game time.
- PublishDelay returns a CoroutineHandle so a pending publish can be stopped.
- Added BeaconHandle typed payload extensions for one through five payload values.
- Added Get, GetOr, TryGet, Has, IsTopic, HasData, and IsEmpty convenience helpers.
- Multi-value payload helpers use direct positional access without payload scanning or enumeration.
Game Loop
- Updated the game loop to distinguish fixed-update timing from rendered-frame timing.
- Added render-frame tracking used by automatic camera updates.
- Preserved graceful shutdown checks so updates and rendering do not continue after the window closes.