What's New in v0.6.0-beta¶
Released: [Date TBD]
Version 0.6.0-beta brings significant performance optimizations, enhanced query capabilities, and improved developer experience with zero-allocation systems and comprehensive profiling tools.
Major Features¶
Performance Monitoring & Profiling¶
Built-in performance overlay with real-time metrics and detailed profiling:
// Enable performance monitoring
builder.Services.AddPerformanceMonitoring(options =>
{
options.EnableOverlay = true;
options.ShowFPS = true;
options.ShowFrameTime = true;
options.ShowMemory = true;
});
Features: - FPS Counter - Min/max/average tracking with 60-frame history - Frame Time Graph - Visual representation of frame timing - Memory Statistics - GC collection counts and managed memory usage - Rendering Stats - Sprites rendered, draw calls, batch efficiency - Per-System Profiling - Identify performance bottlenecks
Hotkeys:
- F1 - Toggle overlay visibility
- F3 - Toggle detailed stats (includes frame time graph and memory)
See Performance Monitoring Guide
Zero-Allocation Systems¶
Optimized hot paths using ArrayPool<T> and custom object pools to minimize GC pressure:
Entity Component Iteration:
// Safe iteration without allocations
protected internal virtual void OnUpdate(GameTime gameTime)
{
var count = _components.Count;
var array = ArrayPool<Component>.Shared.Rent(count);
try
{
_components.CopyTo(array, 0);
for (int i = 0; i < count; i++)
{
array[i].OnUpdate(gameTime);
}
}
finally
{
ArrayPool<Component>.Shared.Return(array, clearArray: true);
}
}
Particle System Pooling:
private readonly ObjectPool<Particle> _particlePool;
// Get from pool instead of 'new'
var particle = _particlePool.Get();
particle.Position = spawnPos;
particle.Velocity = velocity;
// Return to pool when done
_particlePool.Return(particle);
Query System Optimization:
// Random entity selection uses ArrayPool
var randomEnemy = _world.Query()
.With<EnemyComponent>()
.Random(); // Zero allocation!
See Performance Optimization Guide
Sprite Batching & Culling¶
Automatic batching with intelligent layer sorting and frustum culling:
var sprite = entity.AddComponent<SpriteComponent>();
sprite.TexturePath = "assets/player.png";
sprite.Layer = 10; // Higher layers render on top
sprite.Tint = Color.White;
// Check batching efficiency
var (renderedCount, drawCalls) = spriteSystem.GetBatchStats();
Logger.LogInfo($"Rendered {renderedCount} sprites in {drawCalls} draw calls");
Features: - Automatic Batching - Groups sprites by texture to minimize draw calls - Layer Sorting - Correct rendering order with configurable layers - Frustum Culling - Off-screen sprites automatically skipped - Batch Statistics - Real-time efficiency metrics
Performance: - 10,000+ sprites at 60 FPS with proper batching - 10-50x reduction in draw calls vs naive rendering - Zero allocation during rendering
Advanced Query System¶
Powerful spatial queries, component filtering, and sorting:
Spatial Queries:
// Find entities within radius
var nearbyEnemies = _world.Query()
.WithinRadius(playerPos, 200f)
.With<EnemyComponent>()
.Execute();
// Find entities within bounds
var visibleEntities = _world.Query()
.WithinBounds(new Rectangle(0, 0, 1280, 720))
.Execute();
Component Filtering:
// Filter by component properties
var lowHealthEnemies = _world.Query()
.With<HealthComponent>(h => h.CurrentHealth < 50)
.With<EnemyComponent>()
.Execute();
Sorting & Pagination:
// Get 5 nearest enemies
var nearest = _world.Query()
.With<EnemyComponent>()
.OrderBy(e => Vector2.Distance(
e.GetComponent<TransformComponent>().Position,
playerPosition))
.Take(5)
.Execute();
// Paginate results
var page2 = _world.Query()
.With<ItemComponent>()
.Skip(10)
.Take(10)
.Execute();
Multi-Tag Queries:
// Must have ALL tags
var bosses = _world.Query()
.WithAllTags("Enemy", "Boss", "Elite")
.Execute();
// Must have ANY tag
var targets = _world.Query()
.WithAnyTag("Enemy", "NPC", "Breakable")
.Execute();
Query Cloning:
// Create base query
var enemyQuery = _world.Query()
.With<EnemyComponent>()
.Without<DeadComponent>();
// Clone and customize
var weakEnemies = enemyQuery.Clone()
.With<HealthComponent>(h => h.CurrentHealth < 30)
.Execute();
var strongEnemies = enemyQuery.Clone()
.With<HealthComponent>(h => h.CurrentHealth > 80)
.OrderByDescending(e => e.GetComponent<HealthComponent>().CurrentHealth)
.Execute();
Camera Follow System¶
Automatic camera tracking with smooth movement and constraints:
var cameraFollow = player.AddComponent<CameraFollowComponent>();
cameraFollow.CameraName = "Main";
cameraFollow.Smoothing = 5f; // Higher = slower, smoother follow
cameraFollow.Offset = new Vector2(0, -50); // Camera offset from target
cameraFollow.Deadzone = new Vector2(50, 30); // Don't move within deadzone
cameraFollow.FollowX = true; // Follow horizontal movement
cameraFollow.FollowY = true; // Follow vertical movement
cameraFollow.Priority = 10; // Higher priority targets take precedence
Features: - Smooth Following - Configurable smoothing/lerp speed - Deadzone Support - Reduce camera jitter - Offset Control - Position camera relative to target - Priority System - Multiple targets with automatic switching - Axis Control - Enable/disable X or Y following independently
Enhanced Particle System¶
Pooled particle effects with zero GC pressure:
var emitter = entity.AddComponent<ParticleEmitterComponent>();
emitter.IsEmitting = true;
emitter.EmissionRate = 50f; // Particles per second
emitter.MaxParticles = 200;
emitter.ParticleLifetime = 2f;
// Appearance
emitter.StartColor = new Color(255, 200, 0, 255);
emitter.EndColor = new Color(255, 50, 0, 0); // Fade to transparent
emitter.StartSize = 8f;
emitter.EndSize = 2f;
// Physics
emitter.InitialVelocity = new Vector2(0, -50);
emitter.VelocitySpread = 30f; // Random angle variance
emitter.Gravity = new Vector2(0, 100);
emitter.SpawnRadius = 10f; // Random spawn area
// Statistics
Logger.LogInfo($"Active particles: {emitter.ParticleCount}");
Features: - Object Pooling - Particles reused, zero GC allocations - Color Interpolation - Smooth color transitions - Size Interpolation - Shrink/grow over lifetime - Physics Simulation - Gravity and velocity - Configurable Emission - Rate, lifetime, and spawn area - Performance Stats - Track active particle count
API Improvements¶
Cached Entity Queries¶
High-performance queries that automatically update:
// Create cached query (one-time setup)
var movingEntities = _world.CreateCachedQuery<TransformComponent, VelocityComponent>();
// Use in systems (zero allocation!)
public void Update(GameTime gameTime)
{
foreach (var entity in movingEntities.Execute())
{
var transform = entity.GetComponent<TransformComponent>();
var velocity = entity.GetComponent<VelocityComponent>();
transform.Position += velocity.Velocity * deltaTime;
}
}
Benefits: - Results cached and automatically invalidated on entity/component changes - Zero allocation per frame - Supports up to 3 component types - Perfect for system hot paths
Transform Hierarchy Improvements¶
Better memory management for parent/child relationships:
// Clear all children efficiently (uses ArrayPool)
transform.ClearChildren();
// Iterate children without allocation
foreach (var child in transform.Children)
{
// Process child
}
Bug Fixes¶
Performance¶
- Fixed memory leak in particle system when particles expired
- Fixed unnecessary allocations in
Entity.OnUpdate()component iteration - Fixed allocation in
ParticleSystem.Render()(removed.ToList()) - Optimized
EntityQuery.Random()to useArrayPool<T>
ECS¶
- Fixed entity component iteration thread safety issues
- Fixed transform hierarchy cleanup on entity destruction
- Fixed cached query invalidation edge cases
Rendering¶
- Fixed sprite batching layer sorting inconsistencies
- Fixed camera follow jitter with high smoothing values
- Fixed frustum culling boundary precision issues
Input¶
- Fixed text input handling for special keys (backspace, delete, enter)
- Fixed gamepad axis deadzone calculations
Documentation¶
New Guides¶
- Performance Monitoring - FPS counter, profiling, and metrics
- Performance Optimization - Zero-allocation patterns, pooling
- Particle System - Creating particle effects
- Advanced Queries - Updated with spatial queries and filtering
Updated Guides¶
- Camera System - Added camera follow component
- Drawing Primitives - Corrected hotkey documentation
- ECS Getting Started - Added pooling best practices
New Demo Scenes¶
Performance Benchmark Scene¶
Stress test sprite batching with 10,000+ sprites:
cd samples/FeatureDemos
dotnet run
# Select "Performance Benchmark" from menu
Features: - Add/remove sprites dynamically (UP/DOWN: ±100, LEFT/RIGHT: ±1000) - Move camera to see frustum culling (WASD) - Zoom camera (Q/E) - Toggle culling visualization (C) - Real-time batching statistics
Enhanced Query Demo¶
Interactive demonstration of all query features:
- Spatial queries (WithinRadius, WithinBounds)
- Component filtering with predicates
- Multi-tag queries (WithAllTags, WithAnyTag)
- Sorting and pagination
- Random selection
- Query cloning
Enhanced Particle Demo¶
5 pre-configured particle effects:
- Fire
- Explosion
- Smoke
- Sparkles
- Trail
Toggle continuous/burst emission, adjust parameters in real-time.
Performance Metrics¶
Sprite Rendering¶
- Baseline: 1,000 sprites @ 60 FPS
- Stress Test: 10,000+ sprites @ 60 FPS with batching
- Draw Calls: 1-5 (depending on texture variety)
- Batch Efficiency: 10-50x reduction in draw calls
Memory Management¶
- Entity Updates: Zero allocation (uses
ArrayPool<T>) - Query System: Zero allocation for cached queries
- Particle System: Zero allocation per frame (object pooling)
- GC Collections: Significantly reduced Gen 2 collections
Breaking Changes¶
None!
Version 0.6.0-beta maintains full API compatibility with 0.5.0-beta. All existing code will continue to work without modifications.
Updated Dependencies¶
- .NET 10 SDK - Required
- SDL3-CS - Updated to latest version
- Microsoft.Extensions.* - Updated to .NET 10 versions
Upgrade Guide¶
From 0.5.0-beta¶
Update your package references:
<ItemGroup>
<PackageReference Include="Brine2D.Desktop" Version="0.6.0-beta" />
</ItemGroup>
Or via command line:
dotnet add package Brine2D.Desktop --version 0.6.0-beta
No code changes required! Your 0.5.0-beta code will work as-is.
Optional: Enable Performance Monitoring¶
Add to your game builder:
builder.Services.AddPerformanceMonitoring(options =>
{
options.EnableOverlay = true;
options.ShowFPS = true;
options.ShowFrameTime = true;
options.ShowMemory = true;
});
What's Next (v0.7.0)¶
- GPU Renderer - Complete SDL3 GPU backend
- Texture Atlases - Automatic sprite sheet packing
- Post-Processing - Shaders and effects pipeline
- Spatial Audio - 3D sound positioning
- Multi-Threading - Parallel ECS system execution
- Enhanced Documentation - Video tutorials and advanced guides
Contributors¶
Thank you to everyone who contributed to this release!
- Report bugs: GitHub Issues
- Suggest features: GitHub Discussions
- Contribute code: See CONTRIBUTING.md
Full Changelog: v0.5.0-beta...v0.6.0-beta