A bridge library that renders Avalonia UI controls inside the Stride 3D game engine. It uses Avalonia's headless (offscreen) rendering via Skia to capture UI frames as bitmaps, uploads them as GPU textures, and draws them in the Stride scene — either as fullscreen HUD overlays or as world-space 3D panels.
The repository also includes a dockable editor shell (hierarchy, properties inspector, viewport) built entirely with Avalonia, plus a comprehensive set of property editor controls for inspecting Stride components at runtime.
| Project | Description |
|---|---|
| Stride.Avalonia | Core bridge library — headless rendering, input forwarding, texture atlas batching, profiling |
| Stride.Avalonia.Editor | Dockable editor shell with hierarchy tree, property inspector, and viewport |
| Stride.Avalonia.Editor.Controls | Specialised property editor controls (vectors, colors, entity references, etc.) |
| Doprez.Stride.Avalonia.Demo | Demo game showcasing fullscreen overlays and 1000 world-space panels |
| Stride.Avalonia.Tests | 1000-panel stress test with FPS benchmarking |
- Headless Avalonia rendering — full Avalonia UI (controls, layout, data binding, themes) rendered offscreen via Skia and uploaded as GPU textures into Stride
- Fullscreen overlays — HUD and menu panels that auto-resize to match the back buffer
- World-space 3D panels — UI floating in the 3D scene with configurable size, resolution, billboarding, and frustum culling
- Complete input forwarding — mouse (move, click, scroll), keyboard (press/release), and text input from Stride to Avalonia
- 3D panel ray-casting — mouse interaction with world-space panels via ray-cast hit testing
- Texture atlas batching — multiple world-space panels packed into shared atlas textures for batched GPU draw calls; auto-growth up to 4096x4096
- Zero-allocation input bridge — compiled expression delegates bypass Avalonia's internal job scheduling (20x calls per event avoided)
- Direct framebuffer access — reflection-based access to
HeadlessWindowImpl._lastRenderedFrameavoids LOH allocations fromCaptureRenderedFrame() - Dirty-update throttling — configurable
MaxDirtyUpdatesPerFramelimits GPU uploads per frame - Frustum culling — AABB-based culling for world-space panels
- Dockable editor shell — Dock.Avalonia-based layout with hierarchy tree, property inspector, menu bar, and 3D viewport
- Reflection-based property inspector — auto-discovery of component properties via Stride attributes (
[DataMember],[Display],[DataMemberRange]); supports 20+ property types - Specialised editors — Vector2/3/4, Quaternion (Euler angles), Color (HSV wheel), entity/component/asset references, lists, dictionaries
- Entity selection highlight — emissive glow effect on selected entities with fade-in/out animation
- Extensible — components can implement
IEditableComponentto customise their editor appearance
- Per-phase timing metrics — update, input, dispatcher, draw, capture, upload, sprite batch
- Panel statistics — drawn/culled/dirty counts per frame
- GC pressure tracking — gen 0/1/2 delta monitoring
- Rolling FPS history — 120-frame history with average and peak frame time
- Benchmark mode — automated performance measurement with stutter detection
- Built-in debug overlay —
DebugPanelcontrol showing FPS, frame time, entity count, draw calls, triangles, memory, and Avalonia metrics
- .NET 10 SDK
- Stride 4.3 (NuGet packages
4.4.0-beta2) - Avalonia 11.3 (pulled automatically via NuGet)
Add the Stride.Avalonia package to your Stride game project:
<PackageReference Include="Doprez.Stride.Avalonia" Version="*" />For the editor shell, also add:
<PackageReference Include="Doprez.Stride.Avalonia.Editor" Version="*" />
<PackageReference Include="Doprez.Stride.Avalonia.Editor.Controls" Version="*" />Create a class inheriting from AvaloniaApp and configure your theme:
using Avalonia;
using Avalonia.Themes.Fluent;
using Stride.Avalonia;
public class MyAvaloniaApp : AvaloniaApp
{
public override void Initialize()
{
Styles.Add(new FluentTheme());
}
}In your platform entry point (e.g., Program.cs), initialize Avalonia before running the game:
using Stride.Engine;
using Stride.Avalonia;
AvaloniaApp.EnsureInitialized<MyAvaloniaApp>();
using var game = new Game();
game.Run();Create a setup script and attach it to an entity in your scene. This registers the AvaloniaSystem and appends the AvaloniaSceneRenderer to the graphics compositor:
using System.Linq;
using Stride.Engine;
using Stride.Avalonia;
using Stride.Rendering.Compositing;
public class AvaloniaSetupScript : SyncScript
{
public override void Start()
{
AvaloniaApp.EnsureInitialized<MyAvaloniaApp>();
if (!Game.GameSystems.OfType<AvaloniaSystem>().Any())
Game.GameSystems.Add(new AvaloniaSystem(Services));
// Append AvaloniaSceneRenderer to the compositor
var compositor = SceneSystem.GraphicsCompositor;
if (compositor?.Game is SceneCameraRenderer cam
&& cam.Child is SceneRendererCollection col
&& !col.Children.OfType<AvaloniaSceneRenderer>().Any())
{
col.Children.Add(new AvaloniaSceneRenderer());
}
}
public override void Update() { }
}Attach an AvaloniaComponent to any entity and assign an AvaloniaPage:
// Fullscreen overlay
var overlay = new AvaloniaComponent
{
Page = new DefaultAvaloniaPage(new MyOverlayControl()),
IsFullscreen = true,
};
entity.Add(overlay);
// World-space 3D panel
var panel = new AvaloniaComponent
{
Page = new DefaultAvaloniaPage(new MyPanelControl()),
IsFullscreen = false,
WorldSize = new Vector2(2f, 1.5f),
Resolution = new Int2(400, 300),
Billboard = true,
};
entity.Add(panel);cd Doprez.Stride.Avalonia.Demo
dotnet run --project Doprez.Stride.Avalonia.Demo.WindowsOn Linux:
cd Doprez.Stride.Avalonia.Demo
dotnet run --project Doprez.Stride.Avalonia.Demo.LinuxThe demo spawns 1000 billboarded world-space Avalonia panels in a 10x10x10 grid plus a fullscreen debug overlay with real-time performance metrics. Press Escape to open the pause menu, which provides Resume, Settings (grid size, camera speeds, mouse sensitivity, window mode, resolution), and Exit. Use F3 to dump metrics, F4 to run a benchmark, and F5 for extended benchmark.
cd Doprez.Stride.Avalonia.Demo
dotnet run --project Stride.Avalonia.TestsSpawns 1000 panels in batches of 50/frame, measures uncapped FPS over 10 seconds, and reports average/min/max FPS with stutter rate.
| Platform | Status |
|---|---|
| Windows (x64) | Supported |
| Linux (x64) | Untested |
The core Stride.Avalonia and Stride.Avalonia.Editor.Controls libraries target net10.0 and are platform-agnostic. The editor shell (Stride.Avalonia.Editor) targets net10.0-windows due to Dock.Avalonia dependencies.
Demos: