![]() |
VOOZH | about |
dotnet add package VitalRouter.MRuby --version 2.6.1
NuGet\Install-Package VitalRouter.MRuby -Version 2.6.1
<PackageReference Include="VitalRouter.MRuby" Version="2.6.1" />
<PackageVersion Include="VitalRouter.MRuby" Version="2.6.1" />Directory.Packages.props
<PackageReference Include="VitalRouter.MRuby" />Project file
paket add VitalRouter.MRuby --version 2.6.1
#r "nuget: VitalRouter.MRuby, 2.6.1"
#:package VitalRouter.MRuby@2.6.1
#addin nuget:?package=VitalRouter.MRuby&version=2.6.1Install as a Cake Addin
#tool nuget:?package=VitalRouter.MRuby&version=2.6.1Install as a Cake Tool
VitalRouter is a high-performance, zero-allocation in-memory messaging library for C#. It is specifically designed for environments where performance and decoupling are critical, such as Unity games or complex .NET applications.
By using simple attributes, you can implement asynchronous handlers, middleware (interceptors), and advanced sequence control. VitalRouter leverages Roslyn Source Generators to produce highly efficient code, promoting a clean, unidirectional control flow with minimal overhead.
Visit vitalrouter.hadashikick.jp for the full documentation.
[Routes] and [Route] to define handlers.VitalRouter follows a simple messaging flow. A Publisher sends a Command to a Router, which then dispatches it through optional Interceptors to one or more Handlers.
---
config:
theme: dark
---
graph LR
Publisher[Publisher] -- PublishAsync --> Router[Router]
subgraph Pipeline
Router -- next --> Interceptor1[Interceptor A]
Interceptor1 -- next --> Interceptor2[Interceptor B]
end
Interceptor2 -- Invoke --> Handler[Handler/Presenter]
Commands are lightweight data structures representing events or actions.
// record structs are recommended for zero-allocation messaging
public readonly record struct MoveCommand(Vector3 Destination) : ICommand;
AOT/HybridCLR Note: While record struct is valid, ensure your AOT metadata is correctly generated for iOS/AOT environments if using tools like HybridCLR.
Use the [Routes] attribute on a partial class to receive commands.
[Routes]
public partial class PlayerPresenter
{
// Use ValueTask for performance in pure .NET projects
[Route]
public async ValueTask On(MoveCommand cmd)
{
await MoveToAsync(cmd.Destination);
}
// Use UniTask for Unity-specific async handling
[Route]
public async UniTask On(SomeAsyncCommand cmd)
{
await DoSomethingAsync();
}
}
Connect your handler to a router and start sending commands.
var router = new Router();
var presenter = new PlayerPresenter();
// MapTo returns a Subscription (IDisposable)
using var subscription = presenter.MapTo(router);
// Publish a message
await router.PublishAsync(new MoveCommand(new Vector3(1, 0, 0)));
You can also subscribe with lambdas instead of using the source generator.
// Simple subscription
router.Subscribe<MoveCommand>(cmd => { /* ... */ });
// Async subscription with ordering
router.SubscribeAwait<MoveCommand>(async (cmd, ct) =>
{
await DoSomethingAsync();
}, CommandOrdering.Sequential);
// Inline interceptors (Filters)
//
// `WithFilter(...)` returns a derived child router that owns the given filter.
// Subscribers registered on the child receive commands published on the parent
// (with the filter applied), just like an Rx `Where` chain forwards items from
// its source.
router
.WithFilter<MoveCommand>(async (cmd, context, next) =>
{
Console.WriteLine("Before");
await next(cmd, context);
Console.WriteLine("After");
})
.Subscribe(cmd => { /* ... */ });
// Publishing on the parent triggers the filter for subscribers on the child:
await router.PublishAsync(new MoveCommand(...));
// → "Before" → handler → "After"
VitalRouter is highly optimized for Unity, especially when combined with UniTask.
When using MapTo in a MonoBehaviour, always bind the subscription to the object's lifecycle.
[Routes]
public partial class CharacterController : MonoBehaviour
{
private void Start()
{
// Bind the subscription to this GameObject's lifecycle
this.MapTo(Router.Default).AddTo(destroyCancellationToken);
}
[Route]
public void On(MoveCommand cmd)
{
transform.position = cmd.Destination;
}
}
Assembly Definition (.asmdef): You must reference VitalRouter in your .asmdef file for the Source Generator to process your [Routes] attributes.
UniTask is a fast async/await library for Unity. VitalRouter actively supports UniTask. Requires: UniTask >= 2.5.5
If UniTask is installed, the VITALROUTER_UNITASK_INTEGRATION flag is defined automatically, enabling optimized GC-free code paths.
| Package | Purpose | Latest version |
|---|---|---|
VitalRouter |
Core messaging and source-generated routing | 👁 NuGet |
VitalRouter.Extensions.DependencyInjection |
DI registration for standard .NET apps | 👁 NuGet |
VitalRouter.R3 |
Bridge commands to R3 reactive streams | 👁 NuGet |
VitalRouter.MRuby |
Publish and handle commands from MRuby scripts | 👁 NuGet |
Since version 2.0, Unity distribution has moved to NuGet.
VitalRouter packages in the NuGet window.Optional Extensions for Unity
Install the following package to use Unity-specific features, including integration with VContainer/UniTask.
https://github.com/hadashiA/VitalRouter.git?path=/src/VitalRouter.Unity/Assets/VitalRouter#2.6.1
You can pipeline async interceptors for published messages. This is a powerful general-purpose pattern for message processing.
<img src="./website/docs/assets/diagram_interceptors.svg" alt="Interceptor Diagram" width="50%" />
R3 is a next-generation Reactive Extensions implementation for C#. VitalRouter integrates with R3.
Control command publishing via external MRuby scripts. MRuby fibers and C# async/await are fully integrated.
Based on large-scale production usage (e.g., HybridFrame):
record struct provides equality comparison and zero-allocation benefits..AddTo(destroyCancellationToken) or manual Dispose() to avoid memory leaks and ghost event handling.UniTask or UniTaskVoid as return types in Unity handlers to leverage optimized pooling. Use ValueTask for pure .NET projects.PublishContext for cross-cutting concerns (logging IDs, cancellation tokens, user permissions) instead of adding those fields to your command structs.CommandOrdering.Sequential for UI animations or dialogue sequences to prevent race conditions.MIT
@hadashiA
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 net5.0 was computed. net5.0-windows net5.0-windows was computed. net6.0 net6.0 was computed. net6.0-android net6.0-android was computed. net6.0-ios net6.0-ios was computed. net6.0-maccatalyst net6.0-maccatalyst was computed. net6.0-macos net6.0-macos was computed. net6.0-tvos net6.0-tvos was computed. net6.0-windows net6.0-windows was computed. net7.0 net7.0 was computed. net7.0-android net7.0-android was computed. net7.0-ios net7.0-ios was computed. net7.0-maccatalyst net7.0-maccatalyst was computed. net7.0-macos net7.0-macos was computed. net7.0-tvos net7.0-tvos was computed. net7.0-windows net7.0-windows was computed. net8.0 net8.0 is compatible. net8.0-android net8.0-android was computed. net8.0-browser net8.0-browser was computed. net8.0-ios net8.0-ios was computed. net8.0-maccatalyst net8.0-maccatalyst was computed. net8.0-macos net8.0-macos was computed. net8.0-tvos net8.0-tvos was computed. net8.0-windows net8.0-windows was computed. net9.0 net9.0 is compatible. net9.0-android net9.0-android was computed. net9.0-browser net9.0-browser was computed. net9.0-ios net9.0-ios was computed. net9.0-maccatalyst net9.0-maccatalyst was computed. net9.0-macos net9.0-macos was computed. net9.0-tvos net9.0-tvos was computed. net9.0-windows net9.0-windows was computed. net10.0 net10.0 was computed. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
| .NET Core | netcoreapp3.0 netcoreapp3.0 was computed. netcoreapp3.1 netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 netstandard2.1 is compatible. |
| MonoAndroid | monoandroid monoandroid was computed. |
| MonoMac | monomac monomac was computed. |
| MonoTouch | monotouch monotouch was computed. |
| Tizen | tizen60 tizen60 was computed. |
| Xamarin.iOS | xamarinios xamarinios was computed. |
| Xamarin.Mac | xamarinmac xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos xamarinwatchos was computed. |
This package is not used by any NuGet packages.
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.6.1 | 94 | 6/3/2026 |
| 2.6.0 | 92 | 6/3/2026 |
| 2.5.0 | 95 | 5/29/2026 |
| 2.4.1 | 104 | 5/12/2026 |
| 2.4.0 | 99 | 5/11/2026 |
| 2.3.0 | 104 | 5/2/2026 |
| 2.2.0 | 151 | 2/18/2026 |
| 2.1.0 | 125 | 2/11/2026 |
| 2.0.5 | 134 | 12/31/2025 |
| 2.0.4 | 288 | 12/15/2025 |
| 2.0.3 | 202 | 11/7/2025 |
| 2.0.2 | 238 | 11/3/2025 |
| 2.0.1 | 221 | 10/31/2025 |
| 2.0.0 | 222 | 10/5/2025 |