com.wallstop-studios.unity-helpers 2.0.0 → 2.0.1

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 (133) hide show
  1. package/.github/workflows/format-on-demand.yml +2 -2
  2. package/.github/workflows/markdown-json.yml +1 -1
  3. package/.github/workflows/npm-publish.yml +1 -1
  4. package/.github/workflows/prettier-autofix.yml +4 -4
  5. package/.github/workflows/yaml-format-lint.yml +1 -1
  6. package/Docs/EFFECTS_SYSTEM.md +1316 -0
  7. package/{EFFECTS_SYSTEM_TUTORIAL.md → Docs/EFFECTS_SYSTEM_TUTORIAL.md} +1 -1
  8. package/{GETTING_STARTED.md → Docs/GETTING_STARTED.md} +10 -8
  9. package/{GLOSSARY.md → Docs/GLOSSARY.md} +4 -4
  10. package/Docs/HELPER_UTILITIES.md +885 -0
  11. package/Docs/HELPER_UTILITIES.md.meta +7 -0
  12. package/{INDEX.md → Docs/INDEX.md} +107 -62
  13. package/Docs/MATH_AND_EXTENSIONS.md +1039 -0
  14. package/{RANDOM_PERFORMANCE.md → Docs/RANDOM_PERFORMANCE.md} +15 -15
  15. package/{RELATIONAL_COMPONENTS.md → Docs/RELATIONAL_COMPONENTS.md} +21 -3
  16. package/{SPATIAL_TREES_2D_GUIDE.md → Docs/SPATIAL_TREES_2D_GUIDE.md} +2 -2
  17. package/{SPATIAL_TREES_3D_GUIDE.md → Docs/SPATIAL_TREES_3D_GUIDE.md} +1 -1
  18. package/{SPATIAL_TREE_2D_PERFORMANCE.md → Docs/SPATIAL_TREE_2D_PERFORMANCE.md} +64 -64
  19. package/{SPATIAL_TREE_3D_PERFORMANCE.md → Docs/SPATIAL_TREE_3D_PERFORMANCE.md} +64 -64
  20. package/Docs/UTILITY_COMPONENTS.md +906 -0
  21. package/Docs/UTILITY_COMPONENTS.md.meta +7 -0
  22. package/Docs/VISUAL_COMPONENTS.md +337 -0
  23. package/Docs/VISUAL_COMPONENTS.md.meta +7 -0
  24. package/Editor/Sprites/AnimationCopier.cs +3 -3
  25. package/README.md +69 -62
  26. package/Runtime/AssemblyInfo.cs +2 -0
  27. package/Runtime/Core/DataStructure/KDTree3D.cs +1 -1
  28. package/Runtime/Core/DataStructure/OctTree3D.cs +1 -1
  29. package/Runtime/Core/Extension/AsyncOperationExtensions.cs +122 -0
  30. package/Runtime/Core/Serialization/ProtobufUnitySurrogates.cs +24 -29
  31. package/Runtime/Integrations/Reflex/AssemblyInfo.cs +7 -0
  32. package/Runtime/Integrations/Reflex/AssemblyInfo.cs.meta +11 -0
  33. package/Runtime/Integrations/Reflex/ContainerRelationalExtensions.cs +198 -0
  34. package/Runtime/Integrations/Reflex/ContainerRelationalExtensions.cs.meta +11 -0
  35. package/Runtime/Integrations/Reflex/RelationalComponentsInstaller.cs +86 -0
  36. package/Runtime/Integrations/Reflex/RelationalComponentsInstaller.cs.meta +11 -0
  37. package/Runtime/Integrations/Reflex/RelationalReflexSceneBootstrapper.cs +316 -0
  38. package/Runtime/Integrations/Reflex/RelationalReflexSceneBootstrapper.cs.meta +11 -0
  39. package/Runtime/Integrations/Reflex/RelationalSceneAssignmentOptions.cs +86 -0
  40. package/Runtime/Integrations/Reflex/RelationalSceneAssignmentOptions.cs.meta +11 -0
  41. package/Runtime/Integrations/Reflex/WallstopStudios.UnityHelpers.Integration.Reflex.asmdef +20 -0
  42. package/Runtime/Integrations/Reflex/WallstopStudios.UnityHelpers.Integration.Reflex.asmdef.meta +7 -0
  43. package/Runtime/Integrations/Reflex.meta +8 -0
  44. package/Runtime/Utils/ScriptableObjectSingleton.cs +1 -1
  45. package/Samples~/DI - Reflex/README.md +527 -0
  46. package/Samples~/DI - Reflex/README.md.meta +7 -0
  47. package/Samples~/DI - Reflex/Scripts/ReflexPaletteService.cs +36 -0
  48. package/Samples~/DI - Reflex/Scripts/ReflexPaletteService.cs.meta +11 -0
  49. package/Samples~/DI - Reflex/Scripts/ReflexRelationalConsumer.cs +79 -0
  50. package/Samples~/DI - Reflex/Scripts/ReflexRelationalConsumer.cs.meta +11 -0
  51. package/Samples~/DI - Reflex/Scripts/ReflexSampleInstaller.cs +30 -0
  52. package/Samples~/DI - Reflex/Scripts/ReflexSampleInstaller.cs.meta +11 -0
  53. package/Samples~/DI - Reflex/Scripts/ReflexSpawner.cs +79 -0
  54. package/Samples~/DI - Reflex/Scripts/ReflexSpawner.cs.meta +11 -0
  55. package/Samples~/DI - Reflex/Scripts/Samples.UnityHelpers.DI.Reflex.asmdef +26 -0
  56. package/Samples~/DI - Reflex/Scripts/Samples.UnityHelpers.DI.Reflex.asmdef.meta +9 -0
  57. package/Samples~/DI - Reflex/Scripts.meta +8 -0
  58. package/Samples~/DI - Reflex.meta +8 -0
  59. package/Samples~/DI - VContainer/README.md +6 -5
  60. package/Samples~/DI - Zenject/README.md +6 -5
  61. package/Tests/Editor/Core/Attributes/RelationalComponentAssignerTests.cs +29 -31
  62. package/Tests/Editor/Integrations/Reflex/ReflexIntegrationCompilationTests.cs +41 -0
  63. package/Tests/Editor/Integrations/Reflex/ReflexIntegrationCompilationTests.cs.meta +11 -0
  64. package/Tests/Editor/Integrations/Reflex/WallstopStudios.UnityHelpers.Tests.Editor.Reflex.asmdef +27 -0
  65. package/Tests/Editor/Integrations/Reflex/WallstopStudios.UnityHelpers.Tests.Editor.Reflex.asmdef.meta +7 -0
  66. package/Tests/Editor/Integrations/Reflex.meta +8 -0
  67. package/Tests/Editor/Integrations/VContainer/VContainerRelationalEntryPointTests.cs +15 -16
  68. package/Tests/Editor/Integrations/VContainer/VContainerRelationalHelpersTests.cs +7 -13
  69. package/Tests/Editor/Integrations/Zenject/ZenjectRelationalHelpersTests.cs +7 -11
  70. package/Tests/Editor/Integrations/Zenject/ZenjectRelationalInitializerTests.cs +19 -21
  71. package/Tests/Editor/PersistentDirectorySettingsTests.cs +0 -1
  72. package/Tests/Editor/Sprites/AnimationCopierFilterTests.cs +0 -1
  73. package/Tests/Editor/Sprites/AnimationViewerWindowTests.cs +2 -2
  74. package/Tests/Editor/Tools/ImageBlurToolTests.cs +1 -1
  75. package/Tests/Editor/Utils/CommonTestBase.cs +17 -0
  76. package/Tests/Editor/Utils/ScriptableObjectSingletonCreatorTests.cs +1 -1
  77. package/Tests/Runtime/Extensions/AsyncOperationExtensionsTests.cs +179 -0
  78. package/Tests/Runtime/Extensions/RandomExtensionTests.cs +55 -0
  79. package/Tests/Runtime/Integrations/Reflex/RelationalComponentsReflexTests.cs +445 -0
  80. package/Tests/Runtime/Integrations/Reflex/RelationalComponentsReflexTests.cs.meta +11 -0
  81. package/Tests/Runtime/Integrations/Reflex/WallstopStudios.UnityHelpers.Tests.Runtime.Reflex.asmdef +28 -0
  82. package/Tests/Runtime/Integrations/Reflex/WallstopStudios.UnityHelpers.Tests.Runtime.Reflex.asmdef.meta +7 -0
  83. package/Tests/Runtime/Integrations/Reflex.meta +8 -0
  84. package/Tests/Runtime/Integrations/VContainer/RelationalComponentsVContainerTests.cs +24 -29
  85. package/Tests/Runtime/Integrations/VContainer/RelationalObjectPoolsVContainerTests.cs +8 -3
  86. package/Tests/Runtime/Integrations/Zenject/RelationalComponentsZenjectTests.cs +10 -20
  87. package/Tests/Runtime/Performance/RandomPerformanceTests.cs +1 -1
  88. package/Tests/Runtime/Performance/SpatialTree2DPerformanceTests.cs +1 -1
  89. package/Tests/Runtime/Performance/SpatialTree3DPerformanceTests.cs +1 -1
  90. package/Tests/Runtime/Serialization/JsonRoundtripComprehensiveTests.cs +4 -9
  91. package/Tests/Runtime/Serialization/ProtoRoundtripComprehensiveTests.cs +13 -13
  92. package/Tests/Runtime/TestUtils/CommonTestBase.cs +11 -0
  93. package/Tests/Runtime/TestUtils/ReflexTestSupport.cs +111 -0
  94. package/Tests/Runtime/TestUtils/ReflexTestSupport.cs.meta +12 -0
  95. package/Tests/Runtime/Utils/MatchColliderToSpriteTests.cs +4 -4
  96. package/Tests/TestUtils.meta +8 -0
  97. package/package.json +6 -1
  98. package/EFFECTS_SYSTEM.md +0 -242
  99. package/MATH_AND_EXTENSIONS.md +0 -316
  100. /package/{CHANGELOG.md → Docs/CHANGELOG.md} +0 -0
  101. /package/{CHANGELOG.md.meta → Docs/CHANGELOG.md.meta} +0 -0
  102. /package/{CONTRIBUTING.md → Docs/CONTRIBUTING.md} +0 -0
  103. /package/{CONTRIBUTING.md.meta → Docs/CONTRIBUTING.md.meta} +0 -0
  104. /package/{DATA_STRUCTURES.md → Docs/DATA_STRUCTURES.md} +0 -0
  105. /package/{DATA_STRUCTURES.md.meta → Docs/DATA_STRUCTURES.md.meta} +0 -0
  106. /package/{EDITOR_TOOLS_GUIDE.md → Docs/EDITOR_TOOLS_GUIDE.md} +0 -0
  107. /package/{EDITOR_TOOLS_GUIDE.md.meta → Docs/EDITOR_TOOLS_GUIDE.md.meta} +0 -0
  108. /package/{EFFECTS_SYSTEM.md.meta → Docs/EFFECTS_SYSTEM.md.meta} +0 -0
  109. /package/{EFFECTS_SYSTEM_TUTORIAL.md.meta → Docs/EFFECTS_SYSTEM_TUTORIAL.md.meta} +0 -0
  110. /package/{GETTING_STARTED.md.meta → Docs/GETTING_STARTED.md.meta} +0 -0
  111. /package/{GLOSSARY.md.meta → Docs/GLOSSARY.md.meta} +0 -0
  112. /package/{HULLS.md → Docs/HULLS.md} +0 -0
  113. /package/{HULLS.md.meta → Docs/HULLS.md.meta} +0 -0
  114. /package/{INDEX.md.meta → Docs/INDEX.md.meta} +0 -0
  115. /package/{LICENSE.md → Docs/LICENSE.md} +0 -0
  116. /package/{LICENSE.md.meta → Docs/LICENSE.md.meta} +0 -0
  117. /package/{MATH_AND_EXTENSIONS.md.meta → Docs/MATH_AND_EXTENSIONS.md.meta} +0 -0
  118. /package/{RANDOM_PERFORMANCE.md.meta → Docs/RANDOM_PERFORMANCE.md.meta} +0 -0
  119. /package/{REFLECTION_HELPERS.md → Docs/REFLECTION_HELPERS.md} +0 -0
  120. /package/{REFLECTION_HELPERS.md.meta → Docs/REFLECTION_HELPERS.md.meta} +0 -0
  121. /package/{RELATIONAL_COMPONENTS.md.meta → Docs/RELATIONAL_COMPONENTS.md.meta} +0 -0
  122. /package/{SERIALIZATION.md → Docs/SERIALIZATION.md} +0 -0
  123. /package/{SERIALIZATION.md.meta → Docs/SERIALIZATION.md.meta} +0 -0
  124. /package/{SINGLETONS.md → Docs/SINGLETONS.md} +0 -0
  125. /package/{SINGLETONS.md.meta → Docs/SINGLETONS.md.meta} +0 -0
  126. /package/{SPATIAL_TREES_2D_GUIDE.md.meta → Docs/SPATIAL_TREES_2D_GUIDE.md.meta} +0 -0
  127. /package/{SPATIAL_TREES_3D_GUIDE.md.meta → Docs/SPATIAL_TREES_3D_GUIDE.md.meta} +0 -0
  128. /package/{SPATIAL_TREE_2D_PERFORMANCE.md.meta → Docs/SPATIAL_TREE_2D_PERFORMANCE.md.meta} +0 -0
  129. /package/{SPATIAL_TREE_3D_PERFORMANCE.md.meta → Docs/SPATIAL_TREE_3D_PERFORMANCE.md.meta} +0 -0
  130. /package/{SPATIAL_TREE_SEMANTICS.md → Docs/SPATIAL_TREE_SEMANTICS.md} +0 -0
  131. /package/{SPATIAL_TREE_SEMANTICS.md.meta → Docs/SPATIAL_TREE_SEMANTICS.md.meta} +0 -0
  132. /package/{THIRD_PARTY_NOTICES.md → Docs/THIRD_PARTY_NOTICES.md} +0 -0
  133. /package/{THIRD_PARTY_NOTICES.md.meta → Docs/THIRD_PARTY_NOTICES.md.meta} +0 -0
package/README.md CHANGED
@@ -22,11 +22,11 @@ Unity Helpers eliminates entire categories of repetitive work with production-re
22
22
 
23
23
  ---
24
24
 
25
- **📚 New to Unity Helpers?** Start here: [Getting Started Guide](GETTING_STARTED.md)
25
+ **📚 New to Unity Helpers?** Start here: [Getting Started Guide](Docs/GETTING_STARTED.md)
26
26
 
27
- **🔍 Looking for something specific?** Check the [Feature Index](INDEX.md)
27
+ **🔍 Looking for something specific?** Check the [Feature Index](Docs/INDEX.md)
28
28
 
29
- **❓ Need a definition?** See the [Glossary](GLOSSARY.md)
29
+ **❓ Need a definition?** See the [Glossary](Docs/GLOSSARY.md)
30
30
 
31
31
  ---
32
32
 
@@ -43,7 +43,7 @@ Unity Helpers eliminates entire categories of repetitive work with production-re
43
43
  | 💾 Need save/load system | [**Serialization**](#serialization) - Unity types just work | 10 minutes |
44
44
  | 🛠️ Manual sprite workflows | [**Editor Tools**](#editor-tools) - 20+ automation tools | 3 minutes |
45
45
 
46
- **Not sure where to start?** → [Getting Started Guide](GETTING_STARTED.md) walks through the top 3 features in 5 minutes.
46
+ **Not sure where to start?** → [Getting Started Guide](Docs/GETTING_STARTED.md) walks through the top 3 features in 5 minutes.
47
47
 
48
48
  ---
49
49
 
@@ -79,7 +79,7 @@ void Awake() => this.AssignRelationalComponents();
79
79
 
80
80
  **Bonus:** Works with VContainer/Zenject for automatic DI + relational wiring!
81
81
 
82
- [📖 Learn More](RELATIONAL_COMPONENTS.md) | [🎯 DI Integration](Samples~/DI%20-%20VContainer/README.md)
82
+ [📖 Learn More](Docs/RELATIONAL_COMPONENTS.md) | [🎯 DI – VContainer](Samples~/DI%20-%20VContainer/README.md) | [🎯 DI – Zenject](Samples~/DI%20-%20Zenject/README.md) | [🎯 DI – Reflex](Samples~/DI%20-%20Reflex/README.md)
83
83
 
84
84
  ---
85
85
 
@@ -106,7 +106,9 @@ player.RemoveAllEffectsWithTag("Haste"); // Batch removal
106
106
  - Cosmetic VFX/SFX that spawn/despawn automatically
107
107
  - Designer-friendly iteration without code changes
108
108
 
109
- [📖 Full Guide](EFFECTS_SYSTEM.md) | [🚀 5-Minute Tutorial](EFFECTS_SYSTEM_TUTORIAL.md)
109
+ **Beyond buffs:** Tags become a powerful capability system for AI decisions, permission gates, state management, and complex gameplay interactions (invulnerability, stealth, elemental systems).
110
+
111
+ [📖 Full Guide](Docs/EFFECTS_SYSTEM.md) | [🚀 5-Minute Tutorial](Docs/EFFECTS_SYSTEM_TUTORIAL.md)
110
112
 
111
113
  ---
112
114
 
@@ -136,7 +138,7 @@ byte[] data = Serializer.JsonSerialize(saveData);
136
138
 
137
139
  **Real-world impact:** Ship updates without worrying about corrupting player saves.
138
140
 
139
- [📖 Serialization Guide](SERIALIZATION.md)
141
+ [📖 Serialization Guide](Docs/SERIALIZATION.md)
140
142
 
141
143
  ---
142
144
 
@@ -186,7 +188,7 @@ void ProcessEnemies(QuadTree2D<Enemy> enemyTree) {
186
188
  - **Prefab Checker**: Validate 200 prefabs for missing references → 1 click (was: manual QA)
187
189
  - **Atlas Generator**: Create sprite atlases from regex/labels → automated (was: manual setup)
188
190
 
189
- [📖 Editor Tools Guide](EDITOR_TOOLS_GUIDE.md)
191
+ [📖 Editor Tools Guide](Docs/EDITOR_TOOLS_GUIDE.md)
190
192
 
191
193
  ---
192
194
 
@@ -267,7 +269,7 @@ int distance = playerName.LevenshteinDistance("jon"); // "john" = 1, close matc
267
269
  string apiKey = "user_name".ToPascalCase(); // "UserName"
268
270
  ```
269
271
 
270
- **Full list:** [Math & Extensions Guide](MATH_AND_EXTENSIONS.md) | [Reflection Helpers](REFLECTION_HELPERS.md)
272
+ **Full list:** [Math & Extensions Guide](Docs/MATH_AND_EXTENSIONS.md) | [Reflection Helpers](Docs/REFLECTION_HELPERS.md)
271
273
 
272
274
  ---
273
275
 
@@ -275,13 +277,13 @@ string apiKey = "user_name".ToPascalCase(); // "UserName"
275
277
 
276
278
  These powerful utilities solve specific problems that waste hours if you implement them yourself:
277
279
 
278
- | Feature | What It Does | Time Saved |
279
- | -------------------------------------------------------------------- | ----------------------------------------------------- | ---------------------------------- |
280
- | **[Predictive Targeting](MATH_AND_EXTENSIONS.md#predictive-target)** | Perfect ballistics for turrets/missiles in one call | 2-3 hours per shooting system |
281
- | **[Coroutine Jitter](MATH_AND_EXTENSIONS.md#unity-extensions)** | Prevents 100 enemies polling on same frame | Eliminates frame spikes |
282
- | **[IL-Emitted Reflection](REFLECTION_HELPERS.md)** | 100x faster than System.Reflection, IL2CPP safe | Critical for serialization/modding |
283
- | **[SmartDestroy()](MATH_AND_EXTENSIONS.md#lifecycle-helpers)** | Editor/runtime safe destruction (no scene corruption) | Prevents countless debugging hours |
284
- | **[Convex/Concave Hulls](HULLS.md)** | Generate territory borders from point clouds | 4-6 hours per hull algorithm |
280
+ | Feature | What It Does | Time Saved |
281
+ | ------------------------------------------------------------------------- | ----------------------------------------------------- | ---------------------------------- |
282
+ | **[Predictive Targeting](Docs/MATH_AND_EXTENSIONS.md#predictive-target)** | Perfect ballistics for turrets/missiles in one call | 2-3 hours per shooting system |
283
+ | **[Coroutine Jitter](Docs/MATH_AND_EXTENSIONS.md#unity-extensions)** | Prevents 100 enemies polling on same frame | Eliminates frame spikes |
284
+ | **[IL-Emitted Reflection](Docs/REFLECTION_HELPERS.md)** | 100x faster than System.Reflection, IL2CPP safe | Critical for serialization/modding |
285
+ | **[SmartDestroy()](Docs/MATH_AND_EXTENSIONS.md#lifecycle-helpers)** | Editor/runtime safe destruction (no scene corruption) | Prevents countless debugging hours |
286
+ | **[Convex/Concave Hulls](Docs/HULLS.md)** | Generate territory borders from point clouds | 4-6 hours per hull algorithm |
285
287
 
286
288
  ---
287
289
 
@@ -435,8 +437,8 @@ Create a `link.xml` file in your `Assets` folder to prevent stripping:
435
437
 
436
438
  - [Unity Manual: Managed Code Stripping](https://docs.unity3d.com/Manual/ManagedCodeStripping.html)
437
439
  - [Protobuf-net and IL2CPP](https://github.com/protobuf-net/protobuf-net#il2cpp)
438
- - [Serialization Guide: IL2CPP Warning](SERIALIZATION.md#️-il2cpp-and-code-stripping-warning)
439
- - [Reflection Helpers: IL2CPP Warning](REFLECTION_HELPERS.md#️-il2cpp-code-stripping-considerations)
440
+ - [Serialization Guide: IL2CPP Warning](Docs/SERIALIZATION.md#️-il2cpp-and-code-stripping-warning)
441
+ - [Reflection Helpers: IL2CPP Warning](Docs/REFLECTION_HELPERS.md#️-il2cpp-code-stripping-considerations)
440
442
 
441
443
  ---
442
444
 
@@ -444,7 +446,7 @@ Create a `link.xml` file in your `Assets` folder to prevent stripping:
444
446
 
445
447
  > 💡 **First time?** Skip to section #1 ([Relational Components](#1--auto-wire-components)) - it has the biggest immediate impact.
446
448
 
447
- Already read the [Top 5 Time-Savers](#-top-5-time-savers)? Jump directly to the [Core Features](#core-features) reference below, or check out the comprehensive [Getting Started Guide](GETTING_STARTED.md).
449
+ Already read the [Top 5 Time-Savers](#-top-5-time-savers)? Jump directly to the [Core Features](#core-features) reference below, or check out the comprehensive [Getting Started Guide](Docs/GETTING_STARTED.md).
448
450
 
449
451
  ---
450
452
 
@@ -527,7 +529,7 @@ IRandom replay = new IllusionFlow(seed: 12345);
527
529
  - Use `PRNG.Instance` for a thread-local default, or use each generator's `TypeName.Instance` (e.g., `IllusionFlow.Instance`, `PcgRandom.Instance`).
528
530
  - Alternatively, create one separate instance per thread.
529
531
 
530
- [📊 Performance Comparison](RANDOM_PERFORMANCE.md)
532
+ [📊 Performance Comparison](Docs/RANDOM_PERFORMANCE.md)
531
533
 
532
534
  ---
533
535
 
@@ -596,9 +598,9 @@ tree.GetElementsInRange(center, radius: 50f, results);
596
598
  - Single queries
597
599
  - Already using Unity's physics system
598
600
 
599
- [📊 2D Benchmarks](SPATIAL_TREE_2D_PERFORMANCE.md) | [📊 3D Benchmarks](SPATIAL_TREE_3D_PERFORMANCE.md)
601
+ [📊 2D Benchmarks](Docs/SPATIAL_TREE_2D_PERFORMANCE.md) | [📊 3D Benchmarks](Docs/SPATIAL_TREE_3D_PERFORMANCE.md)
600
602
 
601
- For behavior details and edge cases, see: [Spatial Tree Semantics](SPATIAL_TREE_SEMANTICS.md)
603
+ For behavior details and edge cases, see: [Spatial Tree Semantics](Docs/SPATIAL_TREE_SEMANTICS.md)
602
604
 
603
605
  ---
604
606
 
@@ -654,7 +656,7 @@ public class Enemy : MonoBehaviour
654
656
  }
655
657
  ```
656
658
 
657
- See the in-depth guide: [Relational Components](RELATIONAL_COMPONENTS.md).
659
+ See the in-depth guide: [Relational Components](Docs/RELATIONAL_COMPONENTS.md).
658
660
 
659
661
  ---
660
662
 
@@ -710,7 +712,9 @@ if (player.HasTag("Stunned")) { /* disable input */ }
710
712
  - `AttributeModification` order: Addition → Multiplication → Override.
711
713
  - `CosmeticEffectData.RequiresInstancing` — instance per application or reuse shared presenters.
712
714
 
713
- Further reading: see the full guide [Effects System](EFFECTS_SYSTEM.md).
715
+ **Power Pattern:** Tags aren't just for buffs—use them to build robust capability systems for invulnerability, AI decision-making, permission gates, state management, and elemental interactions. See [Advanced Scenarios](Docs/EFFECTS_SYSTEM.md#advanced-scenarios-beyond-buffs-and-debuffs) for patterns.
716
+
717
+ Further reading: see the full guide [Effects System](Docs/EFFECTS_SYSTEM.md).
714
718
 
715
719
  ---
716
720
 
@@ -824,7 +828,7 @@ NetworkMessage again = Serializer.Deserialize<NetworkMessage>(buffer.AsSpan(0, l
824
828
  - LZMA compression utilities (see `Runtime/Utils/LZMA.cs`)
825
829
  - Type‑safe serialization and pooled buffers/writers to reduce GC
826
830
 
827
- [Full guide: Serialization](SERIALIZATION.md)
831
+ [Full guide: Serialization](Docs/SERIALIZATION.md)
828
832
 
829
833
  ---
830
834
 
@@ -867,7 +871,7 @@ List<string> matches = commandTrie.GetWordsWithPrefix("tel");
867
871
  // Returns: ["teleport", "tell"]
868
872
  ```
869
873
 
870
- [Full guide: Data Structures](DATA_STRUCTURES.md)
874
+ [Full guide: Data Structures](Docs/DATA_STRUCTURES.md)
871
875
 
872
876
  ---
873
877
 
@@ -875,7 +879,7 @@ List<string> matches = commandTrie.GetWordsWithPrefix("tel");
875
879
 
876
880
  Numeric helpers, geometry primitives, Unity extensions, colors, collections, strings, directions.
877
881
 
878
- See the guide: [Core Math & Extensions](MATH_AND_EXTENSIONS.md).
882
+ See the guide: [Core Math & Extensions](Docs/MATH_AND_EXTENSIONS.md).
879
883
 
880
884
  #### At a Glance
881
885
 
@@ -897,7 +901,7 @@ See the guide: [Core Math & Extensions](MATH_AND_EXTENSIONS.md).
897
901
  - `RuntimeSingleton<T>` — Global component singleton with optional cross‑scene persistence.
898
902
  - `ScriptableObjectSingleton<T>` — Global settings/data singleton loaded from `Resources/`, auto‑created by the editor tool.
899
903
 
900
- See the guide: [Singleton Utilities](SINGLETONS.md) and the tool: [ScriptableObject Singleton Creator](EDITOR_TOOLS_GUIDE.md#scriptableobject-singleton-creator).
904
+ See the guide: [Singleton Utilities](Docs/SINGLETONS.md) and the tool: [ScriptableObject Singleton Creator](Docs/EDITOR_TOOLS_GUIDE.md#scriptableobject-singleton-creator).
901
905
 
902
906
  ---
903
907
 
@@ -911,7 +915,7 @@ Unity Helpers includes 20+ editor tools to streamline your workflow:
911
915
  - **Validation**: Prefab Checker with comprehensive validation rules
912
916
  - **Automation**: ScriptableObject Singleton Creator, Attribute Cache Generator
913
917
 
914
- [📖 Complete Editor Tools Documentation](EDITOR_TOOLS_GUIDE.md)
918
+ [📖 Complete Editor Tools Documentation](Docs/EDITOR_TOOLS_GUIDE.md)
915
919
 
916
920
  **Quick Access:**
917
921
 
@@ -1000,24 +1004,27 @@ void ProcessLargeDataset(int size)
1000
1004
 
1001
1005
  - Zenject/Extenject: `com.extenject.zenject`, `com.modesttree.zenject`, `com.svermeulen.extenject`
1002
1006
  - VContainer: `jp.cysharp.vcontainer`, `jp.hadashikick.vcontainer`
1007
+ - Reflex: `com.gustavopsantos.reflex`
1003
1008
 
1004
1009
  **Manual or source imports (no UPM):**
1005
1010
 
1006
1011
  - Add scripting defines in `Project Settings > Player > Other Settings > Scripting Define Symbols`:
1007
1012
  - `ZENJECT_PRESENT` when Zenject/Extenject is present
1008
1013
  - `VCONTAINER_PRESENT` when VContainer is present
1014
+ - `REFLEX_PRESENT` when Reflex is present
1009
1015
  - Add the define per target platform (e.g., Standalone, Android, iOS).
1010
1016
 
1011
1017
  **Notes:**
1012
1018
 
1013
- - When the define is present, optional assemblies under `Runtime/Integrations/*` compile automatically and expose helpers like `RelationalComponentsInstaller` (Zenject) and `RegisterRelationalComponents()` (VContainer).
1019
+ - When the define is present, optional assemblies under `Runtime/Integrations/*` compile automatically and expose helpers like `RelationalComponentsInstaller` (Zenject/Reflex) and `RegisterRelationalComponents()` (VContainer).
1014
1020
  - If you use UPM, no manual defines are required — the package IDs above trigger symbols via `versionDefines` in the asmdefs.
1015
- - For test scenarios without LifetimeScope (VContainer) or SceneContext (Zenject), see [DI Integrations: Testing and Edge Cases](RELATIONAL_COMPONENTS.md#di-integrations-testing-and-edge-cases) for step‑by‑step patterns.
1021
+ - For test scenarios without LifetimeScope (VContainer) or SceneContext (Zenject), see [DI Integrations: Testing and Edge Cases](Docs/RELATIONAL_COMPONENTS.md#di-integrations-testing-and-edge-cases) for step‑by‑step patterns.
1016
1022
 
1017
1023
  **Quick start:**
1018
1024
 
1019
1025
  - **VContainer**: in your `LifetimeScope.Configure`, call `builder.RegisterRelationalComponents()`.
1020
- - **Zenject**: add `RelationalComponentsInstaller` to your `SceneContext` (toggle scene scan if desired).
1026
+ - **Zenject/Extenject**: add `RelationalComponentsInstaller` to your `SceneContext` (toggle scene scan if desired).
1027
+ - **Reflex**: place `RelationalComponentsInstaller` on the same GameObject as your `SceneScope` to bind the assigner, run the scene scan, and (optionally) listen for additive scenes. Use `container.InjectWithRelations(...)` / `InstantiateGameObjectWithRelations(...)` for DI-friendly hydration.
1021
1028
 
1022
1029
  ```csharp
1023
1030
  // VContainer — LifetimeScope
@@ -1041,7 +1048,7 @@ using WallstopStudios.UnityHelpers.Integrations.Zenject;
1041
1048
  var enemy = Container.InstantiateComponentWithRelations(enemyPrefab, parent);
1042
1049
  ```
1043
1050
 
1044
- See the full guide with scenarios, troubleshooting, and testing patterns: [Relational Components Guide](RELATIONAL_COMPONENTS.md)
1051
+ See the full guide with scenarios, troubleshooting, and testing patterns: [Relational Components Guide](Docs/RELATIONAL_COMPONENTS.md)
1045
1052
 
1046
1053
  ### Additional Helpers
1047
1054
 
@@ -1081,15 +1088,15 @@ Unity Helpers is built with performance as a top priority:
1081
1088
 
1082
1089
  - 10-15x faster than Unity.Random (655-885M ops/sec vs 65-85M ops/sec)
1083
1090
  - Zero GC pressure with thread-local instances
1084
- - [📊 Full Random Performance Benchmarks](RANDOM_PERFORMANCE.md)
1091
+ - [📊 Full Random Performance Benchmarks](Docs/RANDOM_PERFORMANCE.md)
1085
1092
 
1086
1093
  **Spatial Queries:**
1087
1094
 
1088
1095
  - O(log n) tree queries vs O(n) linear search
1089
1096
  - 100-1000x faster for large datasets
1090
1097
  - QuadTree2D: 10,000 objects = ~13 checks vs 10,000 checks
1091
- - [📊 2D Performance Benchmarks](SPATIAL_TREE_2D_PERFORMANCE.md)
1092
- - [📊 3D Performance Benchmarks](SPATIAL_TREE_3D_PERFORMANCE.md)
1098
+ - [📊 2D Performance Benchmarks](Docs/SPATIAL_TREE_2D_PERFORMANCE.md)
1099
+ - [📊 3D Performance Benchmarks](Docs/SPATIAL_TREE_3D_PERFORMANCE.md)
1093
1100
 
1094
1101
  **Memory Management:**
1095
1102
 
@@ -1101,7 +1108,7 @@ Unity Helpers is built with performance as a top priority:
1101
1108
 
1102
1109
  - IL-emitted delegates 10-100x faster than System.Reflection
1103
1110
  - Safe for IL2CPP and AOT platforms
1104
- - [📊 Reflection Performance](REFLECTION_HELPERS.md)
1111
+ - [📊 Reflection Performance](Docs/REFLECTION_HELPERS.md)
1105
1112
 
1106
1113
  ---
1107
1114
 
@@ -1109,40 +1116,40 @@ Unity Helpers is built with performance as a top priority:
1109
1116
 
1110
1117
  **Start Here:**
1111
1118
 
1112
- - 🚀 Getting Started — [Getting Started Guide](GETTING_STARTED.md)
1113
- - 🔍 Feature Index — [Complete A-Z Index](INDEX.md)
1114
- - 📖 Glossary — [Term Definitions](GLOSSARY.md)
1119
+ - 🚀 Getting Started — [Getting Started Guide](Docs/GETTING_STARTED.md)
1120
+ - 🔍 Feature Index — [Complete A-Z Index](Docs/INDEX.md)
1121
+ - 📖 Glossary — [Term Definitions](Docs/GLOSSARY.md)
1115
1122
 
1116
1123
  **Core Guides:**
1117
1124
 
1118
- - Serialization Guide — [Serialization](SERIALIZATION.md)
1119
- - Editor Tools Guide — [Editor Tools](EDITOR_TOOLS_GUIDE.md)
1120
- - Math & Extensions — [Core Math & Extensions](MATH_AND_EXTENSIONS.md)
1121
- - Singletons — [Singleton Utilities](SINGLETONS.md)
1122
- - Relational Components — [Relational Components](RELATIONAL_COMPONENTS.md)
1123
- - Effects System — [Effects System](EFFECTS_SYSTEM.md)
1124
- - Data Structures — [Data Structures](DATA_STRUCTURES.md)
1125
+ - Serialization Guide — [Serialization](Docs/SERIALIZATION.md)
1126
+ - Editor Tools Guide — [Editor Tools](Docs/EDITOR_TOOLS_GUIDE.md)
1127
+ - Math & Extensions — [Core Math & Extensions](Docs/MATH_AND_EXTENSIONS.md)
1128
+ - Singletons — [Singleton Utilities](Docs/SINGLETONS.md)
1129
+ - Relational Components — [Relational Components](Docs/RELATIONAL_COMPONENTS.md)
1130
+ - Effects System — [Effects System](Docs/EFFECTS_SYSTEM.md)
1131
+ - Data Structures — [Data Structures](Docs/DATA_STRUCTURES.md)
1125
1132
 
1126
1133
  **Spatial Trees:**
1127
1134
 
1128
- - 2D Spatial Trees Guide — [2D Spatial Trees Guide](SPATIAL_TREES_2D_GUIDE.md)
1129
- - 3D Spatial Trees Guide — [3D Spatial Trees Guide](SPATIAL_TREES_3D_GUIDE.md)
1130
- - Spatial Tree Semantics — [Spatial Tree Semantics](SPATIAL_TREE_SEMANTICS.md)
1131
- - Spatial Tree 2D Performance — [Spatial Tree 2D Performance](SPATIAL_TREE_2D_PERFORMANCE.md)
1132
- - Spatial Tree 3D Performance — [Spatial Tree 3D Performance](SPATIAL_TREE_3D_PERFORMANCE.md)
1133
- - Hulls (Convex vs Concave) — [Hulls](HULLS.md)
1135
+ - 2D Spatial Trees Guide — [2D Spatial Trees Guide](Docs/SPATIAL_TREES_2D_GUIDE.md)
1136
+ - 3D Spatial Trees Guide — [3D Spatial Trees Guide](Docs/SPATIAL_TREES_3D_GUIDE.md)
1137
+ - Spatial Tree Semantics — [Spatial Tree Semantics](Docs/SPATIAL_TREE_SEMANTICS.md)
1138
+ - Spatial Tree 2D Performance — [Spatial Tree 2D Performance](Docs/SPATIAL_TREE_2D_PERFORMANCE.md)
1139
+ - Spatial Tree 3D Performance — [Spatial Tree 3D Performance](Docs/SPATIAL_TREE_3D_PERFORMANCE.md)
1140
+ - Hulls (Convex vs Concave) — [Hulls](Docs/HULLS.md)
1134
1141
 
1135
1142
  **Performance & Reference:**
1136
1143
 
1137
- - Random Performance — [Random Performance](RANDOM_PERFORMANCE.md)
1138
- - Reflection Helpers — [Reflection Helpers](REFLECTION_HELPERS.md)
1144
+ - Random Performance — [Random Performance](Docs/RANDOM_PERFORMANCE.md)
1145
+ - Reflection Helpers — [Reflection Helpers](Docs/REFLECTION_HELPERS.md)
1139
1146
 
1140
1147
  **Project Info:**
1141
1148
 
1142
- - Changelog — [Changelog](CHANGELOG.md)
1143
- - License — [License](LICENSE.md)
1144
- - Third‑Party Notices — [Third‑Party Notices](THIRD_PARTY_NOTICES.md)
1145
- - Contributing — [Contributing](CONTRIBUTING.md)
1149
+ - Changelog — [Changelog](Docs/CHANGELOG.md)
1150
+ - License — [License](Docs/LICENSE.md)
1151
+ - Third‑Party Notices — [Third‑Party Notices](Docs/THIRD_PARTY_NOTICES.md)
1152
+ - Contributing — [Contributing](Docs/CONTRIBUTING.md)
1146
1153
 
1147
1154
  ---
1148
1155
 
@@ -1161,13 +1168,13 @@ Contributions are welcome! Please feel free to submit a Pull Request.
1161
1168
  - Or run the Actions workflow manually: Actions → "Opt-in Formatting" → Run workflow → enter the PR number.
1162
1169
  - Not everything is auto-fixable: link checks and YAML linting may still require manual changes.
1163
1170
 
1164
- See more details in [CONTRIBUTING](CONTRIBUTING.md).
1171
+ See more details in [CONTRIBUTING](Docs/CONTRIBUTING.md).
1165
1172
 
1166
1173
  ---
1167
1174
 
1168
1175
  ## License
1169
1176
 
1170
- This project is licensed under the MIT License - see the [LICENSE](LICENSE.md) file for details.
1177
+ This project is licensed under the MIT License - see the [LICENSE](Docs/LICENSE.md) file for details.
1171
1178
 
1172
1179
  ## 2.0 Release Notes (Highlights)
1173
1180
 
@@ -1180,4 +1187,4 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE.md) f
1180
1187
  - Minor robustness improvements:
1181
1188
  - Guarded stray `UnityEditor` imports in runtime files to ensure clean player builds.
1182
1189
 
1183
- See [Serialization guide](SERIALIZATION.md) for AOT/IL2CPP guidance and Unity JSON options, and [Editor tools guide](EDITOR_TOOLS_GUIDE.md) for Editor tool usage details.
1190
+ See [Serialization guide](Docs/SERIALIZATION.md) for AOT/IL2CPP guidance and Unity JSON options, and [Editor tools guide](Docs/EDITOR_TOOLS_GUIDE.md) for Editor tool usage details.
@@ -5,5 +5,7 @@ using System.Runtime.CompilerServices;
5
5
  [assembly: InternalsVisibleTo("WallstopStudios.UnityHelpers.Editor")]
6
6
  [assembly: InternalsVisibleTo("WallstopStudios.UnityHelpers.Tests.Runtime.Zenject")]
7
7
  [assembly: InternalsVisibleTo("WallstopStudios.UnityHelpers.Tests.Runtime.VContainer")]
8
+ [assembly: InternalsVisibleTo("WallstopStudios.UnityHelpers.Tests.Runtime.Reflex")]
8
9
  [assembly: InternalsVisibleTo("WallstopStudios.UnityHelpers.Tests.Editor.VContainer")]
9
10
  [assembly: InternalsVisibleTo("WallstopStudios.UnityHelpers.Tests.Editor.Zenject")]
11
+ [assembly: InternalsVisibleTo("WallstopStudios.UnityHelpers.Tests.Editor.Reflex")]
@@ -17,7 +17,7 @@ namespace WallstopStudios.UnityHelpers.Core.DataStructure
17
17
  /// <para>Semantics: Due to algorithmic choices (axis-aligned splitting, half-open containment checks,
18
18
  /// minimum node-size enforcement, and tie-handling on split planes), KdTree3D (balanced and unbalanced)
19
19
  /// may return different edge-case results compared to OctTree3D for identical inputs/queries—especially for
20
- /// points lying exactly on query boundaries or split planes. See SPATIAL_TREE_SEMANTICS.md for details.</para>
20
+ /// points lying exactly on query boundaries or split planes. See Docs/SPATIAL_TREE_SEMANTICS.md for details.</para>
21
21
  /// </remarks>
22
22
  [Serializable]
23
23
  public sealed class KdTree3D<T> : ISpatialTree3D<T>
@@ -16,7 +16,7 @@ namespace WallstopStudios.UnityHelpers.Core.DataStructure
16
16
  /// <para>Cons: Immutable structure by design; rebuild when positions change frequently.</para>
17
17
  /// <para>Semantics: OctTree3D uses octant subdivision and inclusive half-open containment checks with internal
18
18
  /// fast-paths when nodes are fully contained. These choices can lead to different results from KdTree3D for points
19
- /// on boundaries or when numeric precision interacts with minimum node-size adjustments. See SPATIAL_TREE_SEMANTICS.md.</para>
19
+ /// on boundaries or when numeric precision interacts with minimum node-size adjustments. See Docs/SPATIAL_TREE_SEMANTICS.md.</para>
20
20
  /// </remarks>
21
21
  [Serializable]
22
22
  public sealed class OctTree3D<T> : ISpatialTree3D<T>
@@ -271,6 +271,67 @@ namespace WallstopStudios.UnityHelpers.Core.Extension
271
271
  onResult?.Invoke(task.Result);
272
272
  }
273
273
 
274
+ /// <summary>
275
+ /// Converts a Task returning a tuple with two elements to a Unity coroutine (IEnumerator), optionally invoking a callback with the tuple elements.
276
+ /// </summary>
277
+ /// <typeparam name="T1">The type of the first tuple element.</typeparam>
278
+ /// <typeparam name="T2">The type of the second tuple element.</typeparam>
279
+ /// <param name="task">The task to convert.</param>
280
+ /// <param name="onResult">Optional callback invoked with the tuple elements. Can be null.</param>
281
+ /// <returns>An IEnumerator that can be used with StartCoroutine.</returns>
282
+ /// <remarks>
283
+ /// <para>Null handling: Task cannot be null. onResult can be null.</para>
284
+ /// <para>Thread safety: Must be iterated on Unity main thread. No Unity main thread requirement for task execution.</para>
285
+ /// <para>Performance: Delegates work to the generic Task overload. O(1) per iteration.</para>
286
+ /// <para>Allocations: Iterator allocation only.</para>
287
+ /// <para>Edge cases: Returns immediately if task is complete. Propagates task exceptions.</para>
288
+ /// </remarks>
289
+ /// <exception cref="Exception">Throws the task's exception if the task is faulted.</exception>
290
+ public static IEnumerator AsCoroutine<T1, T2>(
291
+ this Task<(T1 First, T2 Second)> task,
292
+ Action<T1, T2> onResult = null
293
+ )
294
+ {
295
+ return task.AsCoroutine(tuple =>
296
+ {
297
+ if (onResult != null)
298
+ {
299
+ onResult(tuple.First, tuple.Second);
300
+ }
301
+ });
302
+ }
303
+
304
+ /// <summary>
305
+ /// Converts a Task returning a tuple with three elements to a Unity coroutine (IEnumerator), optionally invoking a callback with the tuple elements.
306
+ /// </summary>
307
+ /// <typeparam name="T1">The type of the first tuple element.</typeparam>
308
+ /// <typeparam name="T2">The type of the second tuple element.</typeparam>
309
+ /// <typeparam name="T3">The type of the third tuple element.</typeparam>
310
+ /// <param name="task">The task to convert.</param>
311
+ /// <param name="onResult">Optional callback invoked with the tuple elements. Can be null.</param>
312
+ /// <returns>An IEnumerator that can be used with StartCoroutine.</returns>
313
+ /// <remarks>
314
+ /// <para>Null handling: Task cannot be null. onResult can be null.</para>
315
+ /// <para>Thread safety: Must be iterated on Unity main thread. No Unity main thread requirement for task execution.</para>
316
+ /// <para>Performance: Delegates work to the generic Task overload. O(1) per iteration.</para>
317
+ /// <para>Allocations: Iterator allocation only.</para>
318
+ /// <para>Edge cases: Returns immediately if task is complete. Propagates task exceptions.</para>
319
+ /// </remarks>
320
+ /// <exception cref="Exception">Throws the task's exception if the task is faulted.</exception>
321
+ public static IEnumerator AsCoroutine<T1, T2, T3>(
322
+ this Task<(T1 First, T2 Second, T3 Third)> task,
323
+ Action<T1, T2, T3> onResult = null
324
+ )
325
+ {
326
+ return task.AsCoroutine(tuple =>
327
+ {
328
+ if (onResult != null)
329
+ {
330
+ onResult(tuple.First, tuple.Second, tuple.Third);
331
+ }
332
+ });
333
+ }
334
+
274
335
  /// <summary>
275
336
  /// Converts a ValueTask to a Unity coroutine (IEnumerator).
276
337
  /// </summary>
@@ -348,6 +409,67 @@ namespace WallstopStudios.UnityHelpers.Core.Extension
348
409
  onResult?.Invoke(innerTask.Result);
349
410
  }
350
411
 
412
+ /// <summary>
413
+ /// Converts a ValueTask returning a tuple with two elements to a Unity coroutine (IEnumerator), optionally invoking a callback with the tuple elements.
414
+ /// </summary>
415
+ /// <typeparam name="T1">The type of the first tuple element.</typeparam>
416
+ /// <typeparam name="T2">The type of the second tuple element.</typeparam>
417
+ /// <param name="task">The ValueTask to convert.</param>
418
+ /// <param name="onResult">Optional callback invoked with the tuple elements. Can be null.</param>
419
+ /// <returns>An IEnumerator that can be used with StartCoroutine.</returns>
420
+ /// <remarks>
421
+ /// <para>Null handling: ValueTask is a value type and cannot be null. onResult can be null.</para>
422
+ /// <para>Thread safety: Must be iterated on Unity main thread. No Unity main thread requirement for task execution.</para>
423
+ /// <para>Performance: Delegates work to the generic ValueTask overload. O(1) per iteration.</para>
424
+ /// <para>Allocations: Iterator allocation only.</para>
425
+ /// <para>Edge cases: Returns immediately if task is complete. Propagates task exceptions.</para>
426
+ /// </remarks>
427
+ /// <exception cref="Exception">Throws the task's exception if the task is faulted.</exception>
428
+ public static IEnumerator AsCoroutine<T1, T2>(
429
+ this ValueTask<(T1 First, T2 Second)> task,
430
+ Action<T1, T2> onResult = null
431
+ )
432
+ {
433
+ return task.AsCoroutine(tuple =>
434
+ {
435
+ if (onResult != null)
436
+ {
437
+ onResult(tuple.First, tuple.Second);
438
+ }
439
+ });
440
+ }
441
+
442
+ /// <summary>
443
+ /// Converts a ValueTask returning a tuple with three elements to a Unity coroutine (IEnumerator), optionally invoking a callback with the tuple elements.
444
+ /// </summary>
445
+ /// <typeparam name="T1">The type of the first tuple element.</typeparam>
446
+ /// <typeparam name="T2">The type of the second tuple element.</typeparam>
447
+ /// <typeparam name="T3">The type of the third tuple element.</typeparam>
448
+ /// <param name="task">The ValueTask to convert.</param>
449
+ /// <param name="onResult">Optional callback invoked with the tuple elements. Can be null.</param>
450
+ /// <returns>An IEnumerator that can be used with StartCoroutine.</returns>
451
+ /// <remarks>
452
+ /// <para>Null handling: ValueTask is a value type and cannot be null. onResult can be null.</para>
453
+ /// <para>Thread safety: Must be iterated on Unity main thread. No Unity main thread requirement for task execution.</para>
454
+ /// <para>Performance: Delegates work to the generic ValueTask overload. O(1) per iteration.</para>
455
+ /// <para>Allocations: Iterator allocation only.</para>
456
+ /// <para>Edge cases: Returns immediately if task is complete. Propagates task exceptions.</para>
457
+ /// </remarks>
458
+ /// <exception cref="Exception">Throws the task's exception if the task is faulted.</exception>
459
+ public static IEnumerator AsCoroutine<T1, T2, T3>(
460
+ this ValueTask<(T1 First, T2 Second, T3 Third)> task,
461
+ Action<T1, T2, T3> onResult = null
462
+ )
463
+ {
464
+ return task.AsCoroutine(tuple =>
465
+ {
466
+ if (onResult != null)
467
+ {
468
+ onResult(tuple.First, tuple.Second, tuple.Third);
469
+ }
470
+ });
471
+ }
472
+
351
473
  // IEnumerator to Task/ValueTask conversions
352
474
  /// <summary>
353
475
  /// Converts a Unity coroutine (IEnumerator) to a Task.