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.
Files changed (174) hide show
  1. package/.github/workflows/format-on-demand.yml +2 -2
  2. package/.github/workflows/json-format-check.yml +1 -1
  3. package/.github/workflows/markdown-json.yml +1 -1
  4. package/.github/workflows/markdownlint.yml +1 -1
  5. package/.github/workflows/npm-publish.yml +1 -1
  6. package/.github/workflows/prettier-autofix.yml +2 -2
  7. package/.github/workflows/yaml-format-lint.yml +1 -1
  8. package/Docs/Advanced.md +26 -1
  9. package/Docs/Comparisons.md +1229 -146
  10. package/Docs/Compatibility.md +27 -0
  11. package/Docs/DesignAndArchitecture.md +41 -34
  12. package/Docs/EmitShorthands.md +34 -0
  13. package/Docs/Helpers.md +1 -1
  14. package/Docs/Index.md +28 -25
  15. package/Docs/Install.md +29 -6
  16. package/Docs/Integrations/Reflex.md +292 -0
  17. package/Docs/Integrations/Reflex.md.meta +7 -0
  18. package/Docs/Integrations/VContainer.md +324 -0
  19. package/Docs/Integrations/VContainer.md.meta +7 -0
  20. package/Docs/Integrations/Zenject.md +333 -0
  21. package/Docs/Integrations/Zenject.md.meta +7 -0
  22. package/{Editor/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.pdb.meta → Docs/Integrations.meta} +2 -1
  23. package/Docs/InterceptorsAndOrdering.md +371 -17
  24. package/Docs/ListeningPatterns.md +206 -0
  25. package/Docs/MessageBusProviders.md +496 -0
  26. package/Docs/MessageBusProviders.md.meta +7 -0
  27. package/Docs/MessageTypes.md +27 -0
  28. package/Docs/MigrationGuide.md +45 -0
  29. package/Docs/Patterns.md +286 -0
  30. package/Docs/Performance.md +9 -9
  31. package/Docs/QuickReference.md +31 -0
  32. package/Docs/RuntimeConfiguration.md +407 -0
  33. package/Docs/RuntimeConfiguration.md.meta +7 -0
  34. package/Docs/UnityIntegration.md +3 -1
  35. package/Docs/VisualGuide.md +206 -157
  36. package/Editor/CustomEditors/MessagingComponentEditor.cs +15 -6
  37. package/README.md +148 -26
  38. package/Runtime/AssemblyInfo.cs +4 -0
  39. package/Runtime/Core/Extensions/MessageBusExtensions.cs +253 -0
  40. package/Runtime/Core/Extensions/MessageBusExtensions.cs.meta +12 -0
  41. package/Runtime/Core/Extensions/MessageExtensions.cs +137 -89
  42. package/Runtime/Core/MessageBus/GlobalMessageBusProvider.cs +23 -0
  43. package/Runtime/Core/MessageBus/GlobalMessageBusProvider.cs.meta +11 -0
  44. package/Runtime/Core/MessageBus/IMessageBusProvider.cs +14 -0
  45. package/Runtime/Core/MessageBus/IMessageBusProvider.cs.meta +11 -0
  46. package/Runtime/Core/MessageBus/IMessageRegistrationBuilder.cs +18 -0
  47. package/Runtime/Core/MessageBus/IMessageRegistrationBuilder.cs.meta +11 -0
  48. package/Runtime/Core/MessageBus/MessageBusRebindMode.cs +26 -0
  49. package/Runtime/Core/MessageBus/MessageBusRebindMode.cs.meta +11 -0
  50. package/Runtime/Core/MessageBus/MessageRegistrationBuilder.cs +383 -0
  51. package/Runtime/Core/MessageBus/MessageRegistrationBuilder.cs.meta +11 -0
  52. package/Runtime/Core/MessageHandler.cs +198 -27
  53. package/Runtime/Core/MessageRegistrationToken.cs +67 -25
  54. package/Runtime/Unity/CurrentGlobalMessageBusProvider.cs +31 -0
  55. package/Runtime/Unity/CurrentGlobalMessageBusProvider.cs.meta +12 -0
  56. package/Runtime/Unity/InitialGlobalMessageBusProvider.cs +38 -0
  57. package/Runtime/Unity/InitialGlobalMessageBusProvider.cs.meta +12 -0
  58. package/Runtime/Unity/Integrations/Reflex/AssemblyInfo.cs +11 -0
  59. package/Runtime/Unity/Integrations/Reflex/AssemblyInfo.cs.meta +3 -0
  60. package/Runtime/Unity/Integrations/Reflex/ReflexRegistrationInstaller.cs +73 -0
  61. package/Runtime/Unity/Integrations/Reflex/ReflexRegistrationInstaller.cs.meta +11 -0
  62. package/Runtime/Unity/Integrations/Reflex/WallstopStudios.DxMessaging.Reflex.asmdef +20 -0
  63. package/Runtime/Unity/Integrations/Reflex/WallstopStudios.DxMessaging.Reflex.asmdef.meta +7 -0
  64. package/Runtime/Unity/Integrations/Reflex.meta +8 -0
  65. package/Runtime/Unity/Integrations/VContainer/AssemblyInfo.cs +11 -0
  66. package/Runtime/Unity/Integrations/VContainer/AssemblyInfo.cs.meta +3 -0
  67. package/Runtime/Unity/Integrations/VContainer/VContainerRegistrationExtensions.cs +46 -0
  68. package/Runtime/Unity/Integrations/VContainer/VContainerRegistrationExtensions.cs.meta +11 -0
  69. package/Runtime/Unity/Integrations/VContainer/WallstopStudios.DxMessaging.VContainer.asmdef +30 -0
  70. package/Runtime/Unity/Integrations/VContainer/WallstopStudios.DxMessaging.VContainer.asmdef.meta +7 -0
  71. package/Runtime/Unity/Integrations/VContainer.meta +8 -0
  72. package/Runtime/Unity/Integrations/Zenject/AssemblyInfo.cs +11 -0
  73. package/Runtime/Unity/Integrations/Zenject/AssemblyInfo.cs.meta +3 -0
  74. package/Runtime/Unity/Integrations/Zenject/WallstopStudios.DxMessaging.Zenject.asmdef +30 -0
  75. package/Runtime/Unity/Integrations/Zenject/WallstopStudios.DxMessaging.Zenject.asmdef.meta +7 -0
  76. package/Runtime/Unity/Integrations/Zenject/ZenjectRegistrationInstaller.cs +55 -0
  77. package/Runtime/Unity/Integrations/Zenject/ZenjectRegistrationInstaller.cs.meta +11 -0
  78. package/Runtime/Unity/Integrations/Zenject.meta +8 -0
  79. package/Runtime/Unity/Integrations.meta +8 -0
  80. package/Runtime/Unity/MessageAwareComponent.cs +102 -0
  81. package/Runtime/Unity/MessageBusProviderHandle.cs +97 -0
  82. package/Runtime/Unity/MessageBusProviderHandle.cs.meta +12 -0
  83. package/Runtime/Unity/MessagingComponent.cs +164 -2
  84. package/Runtime/Unity/MessagingComponentInstaller.cs +120 -0
  85. package/Runtime/Unity/MessagingComponentInstaller.cs.meta +12 -0
  86. package/Runtime/Unity/ScriptableMessageBusProvider.cs +14 -0
  87. package/Runtime/Unity/ScriptableMessageBusProvider.cs.meta +12 -0
  88. package/Samples~/DI/Prefabs/MessagingInstallerSample.prefab +98 -0
  89. package/Samples~/DI/Prefabs/MessagingInstallerSample.prefab.meta +7 -0
  90. package/Samples~/DI/Prefabs.meta +8 -0
  91. package/Samples~/DI/Providers/GlobalMessageBusProvider.asset +14 -0
  92. package/Samples~/DI/Providers/GlobalMessageBusProvider.asset.meta +8 -0
  93. package/Samples~/DI/Providers/InitialGlobalMessageBusProvider.asset +14 -0
  94. package/Samples~/DI/Providers/InitialGlobalMessageBusProvider.asset.meta +8 -0
  95. package/Samples~/DI/Providers.meta +8 -0
  96. package/Samples~/DI/README.md +51 -0
  97. package/Samples~/DI/README.md.meta +7 -0
  98. package/Samples~/DI/Reflex/SampleInstaller.cs +75 -0
  99. package/Samples~/DI/Reflex/SampleInstaller.cs.meta +11 -0
  100. package/Samples~/DI/Reflex.meta +8 -0
  101. package/Samples~/DI/VContainer/SampleLifetimeScope.cs +81 -0
  102. package/Samples~/DI/VContainer/SampleLifetimeScope.cs.meta +11 -0
  103. package/Samples~/DI/VContainer.meta +8 -0
  104. package/Samples~/DI/Zenject/SampleInstaller.cs +67 -0
  105. package/Samples~/DI/Zenject/SampleInstaller.cs.meta +11 -0
  106. package/Samples~/DI/Zenject.meta +8 -0
  107. package/Samples~/DI.meta +8 -0
  108. package/Samples~/Mini Combat/README.md +5 -7
  109. package/Samples~/Mini Combat/Walkthrough.md +18 -24
  110. package/Samples~/UI Buttons + Inspector/DiagnosticsEnabler.cs +12 -2
  111. package/Samples~/UI Buttons + Inspector/README.md.meta +7 -0
  112. package/Tests/Runtime/Benchmarks/BenchmarkSession.cs +444 -0
  113. package/Tests/Runtime/Benchmarks/BenchmarkSession.cs.meta +11 -0
  114. package/Tests/Runtime/Benchmarks/BenchmarkTestBase.cs +94 -0
  115. package/Tests/Runtime/Benchmarks/BenchmarkTestBase.cs.meta +11 -0
  116. package/Tests/Runtime/Benchmarks/ComparisonPerformanceTests.cs +395 -0
  117. package/Tests/Runtime/Benchmarks/ComparisonPerformanceTests.cs.meta +11 -0
  118. package/Tests/Runtime/Benchmarks/PerformanceTests.cs +77 -429
  119. package/Tests/Runtime/Benchmarks/ProviderResolutionBenchmarks.cs +142 -0
  120. package/Tests/Runtime/Benchmarks/ProviderResolutionBenchmarks.cs.meta +12 -0
  121. package/Tests/Runtime/Benchmarks/WallstopStudios.DxMessaging.Tests.Runtime.Benchmarks.asmdef +50 -0
  122. package/Tests/Runtime/Benchmarks/WallstopStudios.DxMessaging.Tests.Runtime.Benchmarks.asmdef.meta +7 -0
  123. package/Tests/Runtime/Core/DefaultBusFallbackTests.cs +333 -0
  124. package/Tests/Runtime/Core/DefaultBusFallbackTests.cs.meta +11 -0
  125. package/Tests/Runtime/Core/Extensions/MessageBusExtensionsTests.cs +278 -0
  126. package/Tests/Runtime/Core/Extensions/MessageBusExtensionsTests.cs.meta +11 -0
  127. package/Tests/Runtime/Core/Extensions/MessageExtensionsProviderTests.cs +289 -0
  128. package/Tests/Runtime/Core/Extensions/MessageExtensionsProviderTests.cs.meta +11 -0
  129. package/Tests/Runtime/Core/Extensions.meta +8 -0
  130. package/Tests/Runtime/Core/IntegrationShimSmokeTests.cs +57 -0
  131. package/Tests/Runtime/Core/IntegrationShimSmokeTests.cs.meta +11 -0
  132. package/Tests/Runtime/Core/MessageHandlerGlobalBusTests.cs +219 -0
  133. package/Tests/Runtime/Core/MessageHandlerGlobalBusTests.cs.meta +11 -0
  134. package/Tests/Runtime/Core/MessageRegistrationBuilderTests.cs +204 -0
  135. package/Tests/Runtime/Core/MessageRegistrationBuilderTests.cs.meta +11 -0
  136. package/Tests/Runtime/Core/MessagingTestBase.cs +4 -4
  137. package/Tests/Runtime/Core/NominalTests.cs +2 -2
  138. package/Tests/Runtime/Core/TypedShorthandTests.cs +2 -2
  139. package/Tests/Runtime/Core/UntargetedEquivalenceTests.cs +1 -1
  140. package/Tests/Runtime/Core/UntargetedPrefreezeTests.cs +2 -4
  141. package/Tests/Runtime/Integrations/Reflex/ReflexIntegrationTests.cs +162 -0
  142. package/Tests/Runtime/Integrations/Reflex/ReflexIntegrationTests.cs.meta +11 -0
  143. package/Tests/Runtime/Integrations/Reflex/Resources/ReflexSettings.asset +16 -0
  144. package/Tests/Runtime/Integrations/Reflex/Resources/ReflexSettings.asset.meta +8 -0
  145. package/Tests/Runtime/Integrations/Reflex/Resources.meta +8 -0
  146. package/Tests/Runtime/Integrations/Reflex/WallstopStudios.DxMessaging.Tests.Runtime.Reflex.asmdef +27 -0
  147. package/Tests/Runtime/Integrations/Reflex/WallstopStudios.DxMessaging.Tests.Runtime.Reflex.asmdef.meta +7 -0
  148. package/Tests/Runtime/Integrations/Reflex.meta +8 -0
  149. package/Tests/Runtime/Integrations/VContainer/VContainerIntegrationTests.cs +140 -0
  150. package/Tests/Runtime/Integrations/VContainer/VContainerIntegrationTests.cs.meta +11 -0
  151. package/Tests/Runtime/Integrations/VContainer/WallstopStudios.DxMessaging.Tests.Runtime.VContainer.asmdef +37 -0
  152. package/Tests/Runtime/Integrations/VContainer/WallstopStudios.DxMessaging.Tests.Runtime.VContainer.asmdef.meta +7 -0
  153. package/Tests/Runtime/Integrations/VContainer.meta +8 -0
  154. package/Tests/Runtime/Integrations/Zenject/WallstopStudios.DxMessaging.Tests.Runtime.Zenject.asmdef +37 -0
  155. package/Tests/Runtime/Integrations/Zenject/WallstopStudios.DxMessaging.Tests.Runtime.Zenject.asmdef.meta +7 -0
  156. package/Tests/Runtime/Integrations/Zenject/ZenjectIntegrationTests.cs +140 -0
  157. package/Tests/Runtime/Integrations/Zenject/ZenjectIntegrationTests.cs.meta +11 -0
  158. package/Tests/Runtime/Integrations/Zenject.meta +8 -0
  159. package/Tests/Runtime/Integrations.meta +8 -0
  160. package/Tests/Runtime/Scripts/Components/EmptyMessageAwareComponent.cs +1 -1
  161. package/Tests/Runtime/Scripts/Components/GenericMessageAwareComponent.cs +1 -1
  162. package/Tests/Runtime/Scripts/Components/SimpleMessageAwareComponent.cs +1 -1
  163. package/Tests/Runtime/TestUtilities/UnityFixtureBase.cs +64 -0
  164. package/Tests/Runtime/TestUtilities/UnityFixtureBase.cs.meta +12 -0
  165. package/Tests/Runtime/TestUtilities.meta +9 -0
  166. package/Tests/Runtime/Unity/MessageBusProviderAssetTests.cs +57 -0
  167. package/Tests/Runtime/Unity/MessageBusProviderAssetTests.cs.meta +11 -0
  168. package/Tests/Runtime/Unity/MessageBusProviderHandleTests.cs +107 -0
  169. package/Tests/Runtime/Unity/MessageBusProviderHandleTests.cs.meta +12 -0
  170. package/Tests/Runtime/Unity/MessagingComponentProviderIntegrationTests.cs +210 -0
  171. package/Tests/Runtime/Unity/MessagingComponentProviderIntegrationTests.cs.meta +12 -0
  172. package/Tests/Runtime/Unity.meta +9 -0
  173. package/Tests/Runtime/WallstopStudios.DxMessaging.Tests.Runtime.asmdef +3 -1
  174. 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:#fff4e5,stroke:#f0b429
363
- style H fill:#e6f7ff,stroke:#1890ff
364
- style PP fill:#eef7ee,stroke:#52c41a
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
- ```text
435
- ┌─────────────────────────────────────────────────────┐
436
- Message History (last 50) │
437
- ├─────────────────────────────────────────────────────┤
438
- [12:34:56.123] HealthChanged │
439
- │ → amount: 25 │
440
- │ → priority: 0 │
441
- │ → handlers: 3 │
442
- │ │
443
- [12:34:55.987] ItemAdded │
444
- │ → itemId: 42, count: 1 │
445
- │ → priority: 5 │
446
- │ → handlers: 2 │
447
- ├─────────────────────────────────────────────────────┤
448
- Active Registrations │
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 SendMessage](Docs/Comparisons.md)
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 |
@@ -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
+ }
@@ -0,0 +1,12 @@
1
+ fileFormatVersion: 2
2
+ guid: 2d2a3b7979da4f248a398e05be9f83d4
3
+ MonoImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ defaultReferences: []
7
+ executionOrder: 0
8
+ icon: {instanceID: 0}
9
+ userData:
10
+ assetBundleName:
11
+ assetBundleVariant:
12
+