com.wallstop-studios.dxmessaging 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/format-on-demand.yml +2 -2
- package/.github/workflows/json-format-check.yml +1 -1
- package/.github/workflows/markdown-json.yml +1 -1
- package/.github/workflows/markdownlint.yml +1 -1
- package/.github/workflows/npm-publish.yml +1 -1
- package/.github/workflows/prettier-autofix.yml +2 -2
- package/.github/workflows/yaml-format-lint.yml +1 -1
- package/Docs/Advanced.md +26 -1
- package/Docs/Comparisons.md +1229 -146
- package/Docs/Compatibility.md +27 -0
- package/Docs/DesignAndArchitecture.md +41 -34
- package/Docs/EmitShorthands.md +34 -0
- package/Docs/Helpers.md +1 -1
- package/Docs/Index.md +28 -25
- package/Docs/Install.md +29 -6
- package/Docs/Integrations/Reflex.md +292 -0
- package/Docs/Integrations/Reflex.md.meta +7 -0
- package/Docs/Integrations/VContainer.md +324 -0
- package/Docs/Integrations/VContainer.md.meta +7 -0
- package/Docs/Integrations/Zenject.md +333 -0
- package/Docs/Integrations/Zenject.md.meta +7 -0
- package/{Editor/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.pdb.meta → Docs/Integrations.meta} +2 -1
- package/Docs/InterceptorsAndOrdering.md +371 -17
- package/Docs/ListeningPatterns.md +206 -0
- package/Docs/MessageBusProviders.md +496 -0
- package/Docs/MessageBusProviders.md.meta +7 -0
- package/Docs/MessageTypes.md +27 -0
- package/Docs/MigrationGuide.md +45 -0
- package/Docs/Patterns.md +286 -0
- package/Docs/Performance.md +9 -9
- package/Docs/QuickReference.md +31 -0
- package/Docs/RuntimeConfiguration.md +407 -0
- package/Docs/RuntimeConfiguration.md.meta +7 -0
- package/Docs/UnityIntegration.md +3 -1
- package/Docs/VisualGuide.md +206 -157
- package/Editor/CustomEditors/MessagingComponentEditor.cs +15 -6
- package/README.md +148 -26
- package/Runtime/AssemblyInfo.cs +4 -0
- package/Runtime/Core/Extensions/MessageBusExtensions.cs +253 -0
- package/Runtime/Core/Extensions/MessageBusExtensions.cs.meta +12 -0
- package/Runtime/Core/Extensions/MessageExtensions.cs +137 -89
- package/Runtime/Core/MessageBus/GlobalMessageBusProvider.cs +23 -0
- package/Runtime/Core/MessageBus/GlobalMessageBusProvider.cs.meta +11 -0
- package/Runtime/Core/MessageBus/IMessageBusProvider.cs +14 -0
- package/Runtime/Core/MessageBus/IMessageBusProvider.cs.meta +11 -0
- package/Runtime/Core/MessageBus/IMessageRegistrationBuilder.cs +18 -0
- package/Runtime/Core/MessageBus/IMessageRegistrationBuilder.cs.meta +11 -0
- package/Runtime/Core/MessageBus/MessageBusRebindMode.cs +26 -0
- package/Runtime/Core/MessageBus/MessageBusRebindMode.cs.meta +11 -0
- package/Runtime/Core/MessageBus/MessageRegistrationBuilder.cs +383 -0
- package/Runtime/Core/MessageBus/MessageRegistrationBuilder.cs.meta +11 -0
- package/Runtime/Core/MessageHandler.cs +198 -27
- package/Runtime/Core/MessageRegistrationToken.cs +67 -25
- package/Runtime/Unity/CurrentGlobalMessageBusProvider.cs +31 -0
- package/Runtime/Unity/CurrentGlobalMessageBusProvider.cs.meta +12 -0
- package/Runtime/Unity/InitialGlobalMessageBusProvider.cs +38 -0
- package/Runtime/Unity/InitialGlobalMessageBusProvider.cs.meta +12 -0
- package/Runtime/Unity/Integrations/Reflex/AssemblyInfo.cs +11 -0
- package/Runtime/Unity/Integrations/Reflex/AssemblyInfo.cs.meta +3 -0
- package/Runtime/Unity/Integrations/Reflex/ReflexRegistrationInstaller.cs +73 -0
- package/Runtime/Unity/Integrations/Reflex/ReflexRegistrationInstaller.cs.meta +11 -0
- package/Runtime/Unity/Integrations/Reflex/WallstopStudios.DxMessaging.Reflex.asmdef +20 -0
- package/Runtime/Unity/Integrations/Reflex/WallstopStudios.DxMessaging.Reflex.asmdef.meta +7 -0
- package/Runtime/Unity/Integrations/Reflex.meta +8 -0
- package/Runtime/Unity/Integrations/VContainer/AssemblyInfo.cs +11 -0
- package/Runtime/Unity/Integrations/VContainer/AssemblyInfo.cs.meta +3 -0
- package/Runtime/Unity/Integrations/VContainer/VContainerRegistrationExtensions.cs +46 -0
- package/Runtime/Unity/Integrations/VContainer/VContainerRegistrationExtensions.cs.meta +11 -0
- package/Runtime/Unity/Integrations/VContainer/WallstopStudios.DxMessaging.VContainer.asmdef +30 -0
- package/Runtime/Unity/Integrations/VContainer/WallstopStudios.DxMessaging.VContainer.asmdef.meta +7 -0
- package/Runtime/Unity/Integrations/VContainer.meta +8 -0
- package/Runtime/Unity/Integrations/Zenject/AssemblyInfo.cs +11 -0
- package/Runtime/Unity/Integrations/Zenject/AssemblyInfo.cs.meta +3 -0
- package/Runtime/Unity/Integrations/Zenject/WallstopStudios.DxMessaging.Zenject.asmdef +30 -0
- package/Runtime/Unity/Integrations/Zenject/WallstopStudios.DxMessaging.Zenject.asmdef.meta +7 -0
- package/Runtime/Unity/Integrations/Zenject/ZenjectRegistrationInstaller.cs +55 -0
- package/Runtime/Unity/Integrations/Zenject/ZenjectRegistrationInstaller.cs.meta +11 -0
- package/Runtime/Unity/Integrations/Zenject.meta +8 -0
- package/Runtime/Unity/Integrations.meta +8 -0
- package/Runtime/Unity/MessageAwareComponent.cs +102 -0
- package/Runtime/Unity/MessageBusProviderHandle.cs +97 -0
- package/Runtime/Unity/MessageBusProviderHandle.cs.meta +12 -0
- package/Runtime/Unity/MessagingComponent.cs +164 -2
- package/Runtime/Unity/MessagingComponentInstaller.cs +120 -0
- package/Runtime/Unity/MessagingComponentInstaller.cs.meta +12 -0
- package/Runtime/Unity/ScriptableMessageBusProvider.cs +14 -0
- package/Runtime/Unity/ScriptableMessageBusProvider.cs.meta +12 -0
- package/Samples~/DI/Prefabs/MessagingInstallerSample.prefab +98 -0
- package/Samples~/DI/Prefabs/MessagingInstallerSample.prefab.meta +7 -0
- package/Samples~/DI/Prefabs.meta +8 -0
- package/Samples~/DI/Providers/GlobalMessageBusProvider.asset +14 -0
- package/Samples~/DI/Providers/GlobalMessageBusProvider.asset.meta +8 -0
- package/Samples~/DI/Providers/InitialGlobalMessageBusProvider.asset +14 -0
- package/Samples~/DI/Providers/InitialGlobalMessageBusProvider.asset.meta +8 -0
- package/Samples~/DI/Providers.meta +8 -0
- package/Samples~/DI/README.md +51 -0
- package/Samples~/DI/README.md.meta +7 -0
- package/Samples~/DI/Reflex/SampleInstaller.cs +75 -0
- package/Samples~/DI/Reflex/SampleInstaller.cs.meta +11 -0
- package/Samples~/DI/Reflex.meta +8 -0
- package/Samples~/DI/VContainer/SampleLifetimeScope.cs +81 -0
- package/Samples~/DI/VContainer/SampleLifetimeScope.cs.meta +11 -0
- package/Samples~/DI/VContainer.meta +8 -0
- package/Samples~/DI/Zenject/SampleInstaller.cs +67 -0
- package/Samples~/DI/Zenject/SampleInstaller.cs.meta +11 -0
- package/Samples~/DI/Zenject.meta +8 -0
- package/Samples~/DI.meta +8 -0
- package/Samples~/Mini Combat/README.md +5 -7
- package/Samples~/Mini Combat/Walkthrough.md +18 -24
- package/Samples~/UI Buttons + Inspector/DiagnosticsEnabler.cs +12 -2
- package/Samples~/UI Buttons + Inspector/README.md.meta +7 -0
- package/Tests/Runtime/Benchmarks/BenchmarkSession.cs +444 -0
- package/Tests/Runtime/Benchmarks/BenchmarkSession.cs.meta +11 -0
- package/Tests/Runtime/Benchmarks/BenchmarkTestBase.cs +94 -0
- package/Tests/Runtime/Benchmarks/BenchmarkTestBase.cs.meta +11 -0
- package/Tests/Runtime/Benchmarks/ComparisonPerformanceTests.cs +395 -0
- package/Tests/Runtime/Benchmarks/ComparisonPerformanceTests.cs.meta +11 -0
- package/Tests/Runtime/Benchmarks/PerformanceTests.cs +77 -429
- package/Tests/Runtime/Benchmarks/ProviderResolutionBenchmarks.cs +142 -0
- package/Tests/Runtime/Benchmarks/ProviderResolutionBenchmarks.cs.meta +12 -0
- package/Tests/Runtime/Benchmarks/WallstopStudios.DxMessaging.Tests.Runtime.Benchmarks.asmdef +50 -0
- package/Tests/Runtime/Benchmarks/WallstopStudios.DxMessaging.Tests.Runtime.Benchmarks.asmdef.meta +7 -0
- package/Tests/Runtime/Core/DefaultBusFallbackTests.cs +333 -0
- package/Tests/Runtime/Core/DefaultBusFallbackTests.cs.meta +11 -0
- package/Tests/Runtime/Core/Extensions/MessageBusExtensionsTests.cs +278 -0
- package/Tests/Runtime/Core/Extensions/MessageBusExtensionsTests.cs.meta +11 -0
- package/Tests/Runtime/Core/Extensions/MessageExtensionsProviderTests.cs +289 -0
- package/Tests/Runtime/Core/Extensions/MessageExtensionsProviderTests.cs.meta +11 -0
- package/Tests/Runtime/Core/Extensions.meta +8 -0
- package/Tests/Runtime/Core/IntegrationShimSmokeTests.cs +57 -0
- package/Tests/Runtime/Core/IntegrationShimSmokeTests.cs.meta +11 -0
- package/Tests/Runtime/Core/MessageHandlerGlobalBusTests.cs +219 -0
- package/Tests/Runtime/Core/MessageHandlerGlobalBusTests.cs.meta +11 -0
- package/Tests/Runtime/Core/MessageRegistrationBuilderTests.cs +204 -0
- package/Tests/Runtime/Core/MessageRegistrationBuilderTests.cs.meta +11 -0
- package/Tests/Runtime/Core/MessagingTestBase.cs +4 -4
- package/Tests/Runtime/Core/NominalTests.cs +2 -2
- package/Tests/Runtime/Core/TypedShorthandTests.cs +2 -2
- package/Tests/Runtime/Core/UntargetedEquivalenceTests.cs +1 -1
- package/Tests/Runtime/Core/UntargetedPrefreezeTests.cs +2 -4
- package/Tests/Runtime/Integrations/Reflex/ReflexIntegrationTests.cs +162 -0
- package/Tests/Runtime/Integrations/Reflex/ReflexIntegrationTests.cs.meta +11 -0
- package/Tests/Runtime/Integrations/Reflex/Resources/ReflexSettings.asset +16 -0
- package/Tests/Runtime/Integrations/Reflex/Resources/ReflexSettings.asset.meta +8 -0
- package/Tests/Runtime/Integrations/Reflex/Resources.meta +8 -0
- package/Tests/Runtime/Integrations/Reflex/WallstopStudios.DxMessaging.Tests.Runtime.Reflex.asmdef +27 -0
- package/Tests/Runtime/Integrations/Reflex/WallstopStudios.DxMessaging.Tests.Runtime.Reflex.asmdef.meta +7 -0
- package/Tests/Runtime/Integrations/Reflex.meta +8 -0
- package/Tests/Runtime/Integrations/VContainer/VContainerIntegrationTests.cs +140 -0
- package/Tests/Runtime/Integrations/VContainer/VContainerIntegrationTests.cs.meta +11 -0
- package/Tests/Runtime/Integrations/VContainer/WallstopStudios.DxMessaging.Tests.Runtime.VContainer.asmdef +37 -0
- package/Tests/Runtime/Integrations/VContainer/WallstopStudios.DxMessaging.Tests.Runtime.VContainer.asmdef.meta +7 -0
- package/Tests/Runtime/Integrations/VContainer.meta +8 -0
- package/Tests/Runtime/Integrations/Zenject/WallstopStudios.DxMessaging.Tests.Runtime.Zenject.asmdef +37 -0
- package/Tests/Runtime/Integrations/Zenject/WallstopStudios.DxMessaging.Tests.Runtime.Zenject.asmdef.meta +7 -0
- package/Tests/Runtime/Integrations/Zenject/ZenjectIntegrationTests.cs +140 -0
- package/Tests/Runtime/Integrations/Zenject/ZenjectIntegrationTests.cs.meta +11 -0
- package/Tests/Runtime/Integrations/Zenject.meta +8 -0
- package/Tests/Runtime/Integrations.meta +8 -0
- package/Tests/Runtime/Scripts/Components/EmptyMessageAwareComponent.cs +1 -1
- package/Tests/Runtime/Scripts/Components/GenericMessageAwareComponent.cs +1 -1
- package/Tests/Runtime/Scripts/Components/SimpleMessageAwareComponent.cs +1 -1
- package/Tests/Runtime/TestUtilities/UnityFixtureBase.cs +64 -0
- package/Tests/Runtime/TestUtilities/UnityFixtureBase.cs.meta +12 -0
- package/Tests/Runtime/TestUtilities.meta +9 -0
- package/Tests/Runtime/Unity/MessageBusProviderAssetTests.cs +57 -0
- package/Tests/Runtime/Unity/MessageBusProviderAssetTests.cs.meta +11 -0
- package/Tests/Runtime/Unity/MessageBusProviderHandleTests.cs +107 -0
- package/Tests/Runtime/Unity/MessageBusProviderHandleTests.cs.meta +12 -0
- package/Tests/Runtime/Unity/MessagingComponentProviderIntegrationTests.cs +210 -0
- package/Tests/Runtime/Unity/MessagingComponentProviderIntegrationTests.cs.meta +12 -0
- package/Tests/Runtime/Unity.meta +9 -0
- package/Tests/Runtime/WallstopStudios.DxMessaging.Tests.Runtime.asmdef +3 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -113,6 +113,57 @@ msg.EmitComponentTargeted(chestComponent);
|
|
|
113
113
|
|
|
114
114
|
---
|
|
115
115
|
|
|
116
|
+
## 🔧 Dependency Injection (DI) Compatible
|
|
117
|
+
|
|
118
|
+
**Using Zenject, VContainer, or Reflex?** DxMessaging is fully DI-compatible out of the box!
|
|
119
|
+
|
|
120
|
+
```csharp
|
|
121
|
+
// Inject IMessageBus in any class
|
|
122
|
+
public class PlayerService : IInitializable, IDisposable
|
|
123
|
+
{
|
|
124
|
+
private readonly MessageRegistrationLease _lease;
|
|
125
|
+
|
|
126
|
+
public PlayerService(IMessageRegistrationBuilder builder)
|
|
127
|
+
{
|
|
128
|
+
// Builder automatically resolves your container-managed bus
|
|
129
|
+
_lease = builder.Build(new MessageRegistrationBuildOptions
|
|
130
|
+
{
|
|
131
|
+
Configure = token => token.RegisterUntargeted<PlayerSpawned>(OnSpawn)
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
public void Initialize() => _lease.Activate();
|
|
136
|
+
public void Dispose() => _lease.Dispose();
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Why use DI + Messaging?
|
|
141
|
+
|
|
142
|
+
- **DI for construction** — Inject services, repositories, managers via constructors
|
|
143
|
+
- **Messaging for events** — Reactive, decoupled communication for gameplay events
|
|
144
|
+
- **Best of both worlds** — Clean architecture with testable, isolated buses
|
|
145
|
+
|
|
146
|
+
#### Automatic integration for
|
|
147
|
+
|
|
148
|
+
- ✅ **Zenject/Extenject** — Full-featured DI with extensive Unity support
|
|
149
|
+
- ✅ **VContainer** — Lightweight, high-performance DI with scoped lifetimes
|
|
150
|
+
- ✅ **Reflex** — Minimal API, blazing-fast dependency injection
|
|
151
|
+
|
|
152
|
+
##### Get started
|
|
153
|
+
|
|
154
|
+
- [Zenject Integration Guide](Docs/Integrations/Zenject.md) — Complete setup with examples
|
|
155
|
+
- [VContainer Integration Guide](Docs/Integrations/VContainer.md) — Scoped buses for scene isolation
|
|
156
|
+
- [Reflex Integration Guide](Docs/Integrations/Reflex.md) — Minimal, lightweight patterns
|
|
157
|
+
|
|
158
|
+
##### Core DI concepts
|
|
159
|
+
|
|
160
|
+
- [Runtime Configuration](Docs/RuntimeConfiguration.md) — Setting message buses at runtime, re-binding registrations
|
|
161
|
+
- [Message Bus Providers](Docs/MessageBusProviders.md) — Provider system for design-time and runtime bus configuration
|
|
162
|
+
|
|
163
|
+
**Not using DI?** No problem! DxMessaging works perfectly standalone with zero dependencies.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
116
167
|
## Is DxMessaging Right for You
|
|
117
168
|
|
|
118
169
|
### ✅ Use DxMessaging When
|
|
@@ -123,6 +174,7 @@ msg.EmitComponentTargeted(chestComponent);
|
|
|
123
174
|
- **You value observability** - Need to debug "what fired when?" or track message flow
|
|
124
175
|
- **Teams/long-term maintenance** - Multiple developers, or you'll maintain this code for years
|
|
125
176
|
- **You want decoupling** - Hate when UI classes need references to 15 different game systems
|
|
177
|
+
- **You're using DI frameworks** - Seamless integration with Zenject/VContainer/Reflex (see [DI Compatible](#-dependency-injection-di-compatible))
|
|
126
178
|
|
|
127
179
|
### ❌ Don't Use DxMessaging When
|
|
128
180
|
|
|
@@ -359,9 +411,9 @@ flowchart LR
|
|
|
359
411
|
P[Producer] --> I[Interceptors<br/>validate/mutate]
|
|
360
412
|
I --> H[Handlers<br/>main logic]
|
|
361
413
|
H --> PP[Post-Processors<br/>analytics/logging]
|
|
362
|
-
style I fill:#
|
|
363
|
-
style H fill:#
|
|
364
|
-
style PP fill:#
|
|
414
|
+
style I fill:#ffe7ba,stroke:#d48806,stroke-width:2px,color:#000
|
|
415
|
+
style H fill:#91d5ff,stroke:#096dd9,stroke-width:2px,color:#000
|
|
416
|
+
style PP fill:#b7eb8f,stroke:#389e0d,stroke-width:2px,color:#000
|
|
365
417
|
```
|
|
366
418
|
|
|
367
419
|
### 🎭 Global Observers: Listen to EVERYTHING (Unique Feature!)
|
|
@@ -431,27 +483,22 @@ void OnDamage(ref TookDamage msg) {
|
|
|
431
483
|
|
|
432
484
|
**DxMessaging solution:** Click any `MessageAwareComponent` in the Inspector:
|
|
433
485
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
│ ✓ HealthChanged (priority: 0, called: 847 times) │
|
|
451
|
-
│ ✓ ItemAdded (priority: 5, called: 23 times) │
|
|
452
|
-
│ ✓ TookDamage (priority: 10, called: 1,203 times) │
|
|
453
|
-
└─────────────────────────────────────────────────────┘
|
|
454
|
-
```
|
|
486
|
+
#### Message History (last 50)
|
|
487
|
+
|
|
488
|
+
- `[12:34:56.123] HealthChanged`
|
|
489
|
+
- amount: 25
|
|
490
|
+
- priority: 0
|
|
491
|
+
- handlers: 3
|
|
492
|
+
- `[12:34:55.987] ItemAdded`
|
|
493
|
+
- itemId: 42, count: 1
|
|
494
|
+
- priority: 5
|
|
495
|
+
- handlers: 2
|
|
496
|
+
|
|
497
|
+
##### Active Registrations
|
|
498
|
+
|
|
499
|
+
- ✓ HealthChanged (priority: 0, called: 847 times)
|
|
500
|
+
- ✓ ItemAdded (priority: 5, called: 23 times)
|
|
501
|
+
- ✓ TookDamage (priority: 10, called: 1,203 times)
|
|
455
502
|
|
|
456
503
|
#### Real-world debugging scenarios
|
|
457
504
|
|
|
@@ -473,7 +520,7 @@ void OnDamage(ref TookDamage msg) {
|
|
|
473
520
|
public void TestAchievementSystem() {
|
|
474
521
|
// Create isolated bus - zero global state
|
|
475
522
|
var testBus = new MessageBus();
|
|
476
|
-
var handler = new MessageHandler(new InstanceId(1)) { active = true };
|
|
523
|
+
var handler = new MessageHandler(new InstanceId(1), testBus) { active = true };
|
|
477
524
|
var token = MessageRegistrationToken.Create(handler, testBus);
|
|
478
525
|
|
|
479
526
|
// Test in isolation
|
|
@@ -524,9 +571,64 @@ Important: Inheritance with MessageAwareComponent
|
|
|
524
571
|
- If you need to opt out of string demos, override `RegisterForStringMessages => false` instead of skipping the base call.
|
|
525
572
|
- Don’t hide Unity methods with `new` (e.g., `new void OnEnable()`); always `override` and call `base.*`.
|
|
526
573
|
|
|
574
|
+
### 🧩 DI Framework Integrations
|
|
575
|
+
|
|
576
|
+
DxMessaging works standalone (zero dependencies) or with any major DI framework. For detailed setup guides and code examples:
|
|
577
|
+
|
|
578
|
+
- **[Zenject Integration Guide](Docs/Integrations/Zenject.md)** — Full-featured DI with extensive Unity support
|
|
579
|
+
- **[VContainer Integration Guide](Docs/Integrations/VContainer.md)** — Lightweight DI with scoped lifetimes for scene isolation
|
|
580
|
+
- **[Reflex Integration Guide](Docs/Integrations/Reflex.md)** — Minimal API, blazing-fast performance
|
|
581
|
+
|
|
582
|
+
#### Core DI concepts
|
|
583
|
+
|
|
584
|
+
- **[Runtime Configuration](Docs/RuntimeConfiguration.md)** — Setting and overriding message buses at runtime, re-binding registrations
|
|
585
|
+
- **[Message Bus Providers](Docs/MessageBusProviders.md)** — Provider system and MessageBusProviderHandle for flexible bus configuration
|
|
586
|
+
|
|
587
|
+
Each guide includes:
|
|
588
|
+
|
|
589
|
+
- ✅ Complete setup instructions with installers
|
|
590
|
+
- ✅ Multiple usage patterns (plain classes, MonoBehaviours, direct injection)
|
|
591
|
+
- ✅ Testing examples with isolated buses
|
|
592
|
+
- ✅ Advanced patterns (pooling, scene scopes, signal bridges)
|
|
593
|
+
|
|
594
|
+
See the [🔧 DI Compatible section](#-dependency-injection-di-compatible) above for a quick overview.
|
|
595
|
+
|
|
527
596
|
### 🆚 Comparisons
|
|
528
597
|
|
|
529
|
-
- [Compare with C# events, UnityEvents, and
|
|
598
|
+
- [Compare with Other Unity Messaging Frameworks](Docs/Comparisons.md) — In-depth comparison with UniRx, MessagePipe, Zenject Signals, C# events, UnityEvents, and more
|
|
599
|
+
- [Scriptable Object Architecture (SOA) Compatibility](Docs/Patterns.md#14-compatibility-with-scriptable-object-architecture-soa) — Migration patterns and interoperability with SOA
|
|
600
|
+
|
|
601
|
+
#### Quick Framework Comparison
|
|
602
|
+
|
|
603
|
+
| Framework | Best For | Key Strength | Unity Support | Learning Curve |
|
|
604
|
+
| ------------------- | --------------------------------- | -------------------------------- | ------------------ | -------------- |
|
|
605
|
+
| **DxMessaging** | Unity pub/sub with lifecycle mgmt | Inspector debugging + control | ✅ Built for Unity | ⭐⭐⭐ |
|
|
606
|
+
| **UniRx** | Complex event stream transforms | Reactive operators (LINQ) | ✅ Built for Unity | ⭐⭐ |
|
|
607
|
+
| **MessagePipe** | High-performance DI messaging | Highest throughput (97M ops/sec) | ✅ Built for Unity | ⭐⭐⭐⭐ |
|
|
608
|
+
| **Zenject Signals** | DI-integrated messaging | Zenject ecosystem | ✅ Built for Unity | ⭐⭐ |
|
|
609
|
+
| **C# Events** | Simple, local communication | Minimal overhead | ✅ Native C# | ⭐⭐⭐⭐⭐ |
|
|
610
|
+
|
|
611
|
+
##### Choose DxMessaging when you want
|
|
612
|
+
|
|
613
|
+
- Unity-first design with GameObject/Component targeting
|
|
614
|
+
- Automatic lifecycle management (zero memory leaks)
|
|
615
|
+
- Inspector debugging to see message flow and history
|
|
616
|
+
- Execution order control (priority-based handlers)
|
|
617
|
+
- Message validation/interception pipeline
|
|
618
|
+
- Global observers (listen to all message instances)
|
|
619
|
+
- Post-processing stage (analytics, logging after handlers)
|
|
620
|
+
- No dependencies, plug-and-play setup
|
|
621
|
+
|
|
622
|
+
See [full comparison](Docs/Comparisons.md) for detailed analysis with code examples, performance benchmarks, and decision guides.
|
|
623
|
+
|
|
624
|
+
> **📦 Using Scriptable Object Architecture (SOA)?**
|
|
625
|
+
>
|
|
626
|
+
> DxMessaging can work alongside or replace SOA patterns. See [SOA Compatibility Guide](Docs/Patterns.md#14-compatibility-with-scriptable-object-architecture-soa) for:
|
|
627
|
+
>
|
|
628
|
+
> - Fair comparison of SOA vs. DxMessaging
|
|
629
|
+
> - Migration patterns from GameEvent/FloatVariable to DxMessaging
|
|
630
|
+
> - How to use both systems together (SOs for configs, DxMessaging for events)
|
|
631
|
+
> - When to keep using ScriptableObjects (immutable design data)
|
|
530
632
|
|
|
531
633
|
### 📖 Reference
|
|
532
634
|
|
|
@@ -599,6 +701,26 @@ For OS-specific benchmark tables generated by PlayMode tests, see [Performance B
|
|
|
599
701
|
|
|
600
702
|
## Comparison Table
|
|
601
703
|
|
|
704
|
+
### Comparison with Unity Messaging Frameworks
|
|
705
|
+
|
|
706
|
+
| Feature | DxMessaging | UniRx | MessagePipe | Zenject Signals |
|
|
707
|
+
| ------------------------ | ------------------ | ------------------ | ------------------ | ------------------ |
|
|
708
|
+
| **Unity Compatibility** | ✅ Built for Unity | ✅ Built for Unity | ✅ Built for Unity | ✅ Built for Unity |
|
|
709
|
+
| **Decoupling** | ✅ Full | ✅ Full | ✅ Full | ✅ Full |
|
|
710
|
+
| **Lifecycle Safety** | ✅ Auto | ⚠️ Manual | ⚠️ Manual | ⚠️ DI-managed |
|
|
711
|
+
| **Execution Order** | ✅ Priority | ❌ None | ❌ None | ❌ None |
|
|
712
|
+
| **Type Safety** | ✅ Strong | ✅ Strong | ✅ Strong | ✅ Strong |
|
|
713
|
+
| **Inspector Debug** | ✅ Built-in | ❌ No | ❌ No | ❌ No |
|
|
714
|
+
| **GameObject Targeting** | ✅ Yes | ❌ No | ❌ No | ❌ No |
|
|
715
|
+
| **Global Observers** | ✅ Yes | ❌ No | ❌ No | ❌ No |
|
|
716
|
+
| **Interceptors** | ✅ Pipeline | ❌ No | ⚠️ Filters | ❌ No |
|
|
717
|
+
| **Post-Processing** | ✅ Dedicated | ❌ No | ⚠️ Filters | ❌ No |
|
|
718
|
+
| **Stream Operators** | ❌ No | ✅ Extensive | ❌ No | ⚠️ With UniRx |
|
|
719
|
+
| **Performance** | ✅ Good (14M) | ✅ Good (18M) | ✅ Best (97M) | ⚠️ Moderate (2.5M) |
|
|
720
|
+
| **Dependencies** | ✅ None | ⚠️ UniTask | ✅ None | ⚠️ Zenject |
|
|
721
|
+
|
|
722
|
+
### Comparison with Traditional Approaches
|
|
723
|
+
|
|
602
724
|
| Feature | DxMessaging | C# Events | UnityEvents | Static Event Bus |
|
|
603
725
|
| ---------------------- | ------------- | ------------ | ------------- | ---------------- |
|
|
604
726
|
| **Decoupling** | ✅ Full | ❌ Tight | ⚠️ Hidden | ✅ Yes |
|
package/Runtime/AssemblyInfo.cs
CHANGED
|
@@ -5,3 +5,7 @@ using System.Runtime.CompilerServices;
|
|
|
5
5
|
AllInternalsVisible = true
|
|
6
6
|
)]
|
|
7
7
|
[assembly: InternalsVisibleTo("WallstopStudios.DxMessaging.Editor")]
|
|
8
|
+
[assembly: InternalsVisibleTo("WallstopStudios.DxMessaging.Tests.Runtime")]
|
|
9
|
+
[assembly: InternalsVisibleTo("WallstopStudios.DxMessaging.Tests.Runtime.Reflex")]
|
|
10
|
+
[assembly: InternalsVisibleTo("WallstopStudios.DxMessaging.Tests.Runtime.VContainer")]
|
|
11
|
+
[assembly: InternalsVisibleTo("WallstopStudios.DxMessaging.Tests.Runtime.Zenject")]
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
namespace DxMessaging.Core.Extensions
|
|
2
|
+
{
|
|
3
|
+
using System;
|
|
4
|
+
using DxMessaging.Core;
|
|
5
|
+
using DxMessaging.Core.MessageBus;
|
|
6
|
+
using DxMessaging.Core.Messages;
|
|
7
|
+
#if UNITY_2017_1_OR_NEWER
|
|
8
|
+
using UnityEngine;
|
|
9
|
+
#endif
|
|
10
|
+
|
|
11
|
+
/// <summary>
|
|
12
|
+
/// <see cref="IMessageBus"/> helpers that mirror the message-centric shorthands in <see cref="MessageExtensions"/>.
|
|
13
|
+
/// </summary>
|
|
14
|
+
public static class MessageBusExtensions
|
|
15
|
+
{
|
|
16
|
+
public static void EmitUntargeted<TMessage>(this IMessageBus messageBus, TMessage message)
|
|
17
|
+
where TMessage : class, IUntargetedMessage
|
|
18
|
+
{
|
|
19
|
+
if (messageBus == null)
|
|
20
|
+
{
|
|
21
|
+
throw new ArgumentNullException(nameof(messageBus));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
message.EmitUntargeted(messageBus);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public static void EmitUntargeted<TMessage>(
|
|
28
|
+
this IMessageBus messageBus,
|
|
29
|
+
ref TMessage message
|
|
30
|
+
)
|
|
31
|
+
where TMessage : struct, IUntargetedMessage
|
|
32
|
+
{
|
|
33
|
+
if (messageBus == null)
|
|
34
|
+
{
|
|
35
|
+
throw new ArgumentNullException(nameof(messageBus));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
message.EmitUntargeted(messageBus);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public static void EmitTargeted<TMessage>(
|
|
42
|
+
this IMessageBus messageBus,
|
|
43
|
+
InstanceId target,
|
|
44
|
+
TMessage message
|
|
45
|
+
)
|
|
46
|
+
where TMessage : class, ITargetedMessage
|
|
47
|
+
{
|
|
48
|
+
if (messageBus == null)
|
|
49
|
+
{
|
|
50
|
+
throw new ArgumentNullException(nameof(messageBus));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
message.EmitTargeted(target, messageBus);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
public static void EmitTargeted<TMessage>(
|
|
57
|
+
this IMessageBus messageBus,
|
|
58
|
+
InstanceId target,
|
|
59
|
+
ref TMessage message
|
|
60
|
+
)
|
|
61
|
+
where TMessage : struct, ITargetedMessage
|
|
62
|
+
{
|
|
63
|
+
if (messageBus == null)
|
|
64
|
+
{
|
|
65
|
+
throw new ArgumentNullException(nameof(messageBus));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
message.EmitTargeted(target, messageBus);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
public static void EmitBroadcast<TMessage>(
|
|
72
|
+
this IMessageBus messageBus,
|
|
73
|
+
InstanceId source,
|
|
74
|
+
TMessage message
|
|
75
|
+
)
|
|
76
|
+
where TMessage : class, IBroadcastMessage
|
|
77
|
+
{
|
|
78
|
+
if (messageBus == null)
|
|
79
|
+
{
|
|
80
|
+
throw new ArgumentNullException(nameof(messageBus));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
message.EmitBroadcast(source, messageBus);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
public static void EmitBroadcast<TMessage>(
|
|
87
|
+
this IMessageBus messageBus,
|
|
88
|
+
InstanceId source,
|
|
89
|
+
ref TMessage message
|
|
90
|
+
)
|
|
91
|
+
where TMessage : struct, IBroadcastMessage
|
|
92
|
+
{
|
|
93
|
+
if (messageBus == null)
|
|
94
|
+
{
|
|
95
|
+
throw new ArgumentNullException(nameof(messageBus));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
message.EmitBroadcast(source, messageBus);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
#if UNITY_2017_1_OR_NEWER
|
|
102
|
+
public static void EmitGameObjectTargeted<TMessage>(
|
|
103
|
+
this IMessageBus messageBus,
|
|
104
|
+
GameObject target,
|
|
105
|
+
TMessage message
|
|
106
|
+
)
|
|
107
|
+
where TMessage : class, ITargetedMessage
|
|
108
|
+
{
|
|
109
|
+
if (messageBus == null)
|
|
110
|
+
{
|
|
111
|
+
throw new ArgumentNullException(nameof(messageBus));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
message.EmitGameObjectTargeted(target, messageBus);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
public static void EmitGameObjectTargeted<TMessage>(
|
|
118
|
+
this IMessageBus messageBus,
|
|
119
|
+
GameObject target,
|
|
120
|
+
ref TMessage message
|
|
121
|
+
)
|
|
122
|
+
where TMessage : struct, ITargetedMessage
|
|
123
|
+
{
|
|
124
|
+
if (messageBus == null)
|
|
125
|
+
{
|
|
126
|
+
throw new ArgumentNullException(nameof(messageBus));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
message.EmitGameObjectTargeted(target, messageBus);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
public static void EmitComponentTargeted<TMessage>(
|
|
133
|
+
this IMessageBus messageBus,
|
|
134
|
+
Component target,
|
|
135
|
+
TMessage message
|
|
136
|
+
)
|
|
137
|
+
where TMessage : class, ITargetedMessage
|
|
138
|
+
{
|
|
139
|
+
if (messageBus == null)
|
|
140
|
+
{
|
|
141
|
+
throw new ArgumentNullException(nameof(messageBus));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
message.EmitComponentTargeted(target, messageBus);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
public static void EmitComponentTargeted<TMessage>(
|
|
148
|
+
this IMessageBus messageBus,
|
|
149
|
+
Component target,
|
|
150
|
+
ref TMessage message
|
|
151
|
+
)
|
|
152
|
+
where TMessage : struct, ITargetedMessage
|
|
153
|
+
{
|
|
154
|
+
if (messageBus == null)
|
|
155
|
+
{
|
|
156
|
+
throw new ArgumentNullException(nameof(messageBus));
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
message.EmitComponentTargeted(target, messageBus);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
public static void EmitGameObjectBroadcast<TMessage>(
|
|
163
|
+
this IMessageBus messageBus,
|
|
164
|
+
GameObject source,
|
|
165
|
+
TMessage message
|
|
166
|
+
)
|
|
167
|
+
where TMessage : class, IBroadcastMessage
|
|
168
|
+
{
|
|
169
|
+
if (messageBus == null)
|
|
170
|
+
{
|
|
171
|
+
throw new ArgumentNullException(nameof(messageBus));
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
message.EmitGameObjectBroadcast(source, messageBus);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
public static void EmitGameObjectBroadcast<TMessage>(
|
|
178
|
+
this IMessageBus messageBus,
|
|
179
|
+
GameObject source,
|
|
180
|
+
ref TMessage message
|
|
181
|
+
)
|
|
182
|
+
where TMessage : struct, IBroadcastMessage
|
|
183
|
+
{
|
|
184
|
+
if (messageBus == null)
|
|
185
|
+
{
|
|
186
|
+
throw new ArgumentNullException(nameof(messageBus));
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
message.EmitGameObjectBroadcast(source, messageBus);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
public static void EmitComponentBroadcast<TMessage>(
|
|
193
|
+
this IMessageBus messageBus,
|
|
194
|
+
Component source,
|
|
195
|
+
TMessage message
|
|
196
|
+
)
|
|
197
|
+
where TMessage : class, IBroadcastMessage
|
|
198
|
+
{
|
|
199
|
+
if (messageBus == null)
|
|
200
|
+
{
|
|
201
|
+
throw new ArgumentNullException(nameof(messageBus));
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
message.EmitComponentBroadcast(source, messageBus);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
public static void EmitComponentBroadcast<TMessage>(
|
|
208
|
+
this IMessageBus messageBus,
|
|
209
|
+
Component source,
|
|
210
|
+
ref TMessage message
|
|
211
|
+
)
|
|
212
|
+
where TMessage : struct, IBroadcastMessage
|
|
213
|
+
{
|
|
214
|
+
if (messageBus == null)
|
|
215
|
+
{
|
|
216
|
+
throw new ArgumentNullException(nameof(messageBus));
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
message.EmitComponentBroadcast(source, messageBus);
|
|
220
|
+
}
|
|
221
|
+
#endif
|
|
222
|
+
|
|
223
|
+
public static void Emit(this IMessageBus messageBus, string payload)
|
|
224
|
+
{
|
|
225
|
+
if (messageBus == null)
|
|
226
|
+
{
|
|
227
|
+
throw new ArgumentNullException(nameof(messageBus));
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
payload.Emit(messageBus);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
public static void EmitAt(this IMessageBus messageBus, InstanceId target, string payload)
|
|
234
|
+
{
|
|
235
|
+
if (messageBus == null)
|
|
236
|
+
{
|
|
237
|
+
throw new ArgumentNullException(nameof(messageBus));
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
payload.Emit(target, messageBus);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
public static void EmitFrom(this IMessageBus messageBus, InstanceId source, string payload)
|
|
244
|
+
{
|
|
245
|
+
if (messageBus == null)
|
|
246
|
+
{
|
|
247
|
+
throw new ArgumentNullException(nameof(messageBus));
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
payload.EmitFrom(source, messageBus);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|