com.wallstop-studios.unity-helpers 2.0.0-rc81.9 → 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 (264) hide show
  1. package/.editorconfig +1 -1
  2. package/.gitattributes +1 -1
  3. package/.githooks/pre-commit +31 -5
  4. package/.githooks/pre-push +50 -0
  5. package/.github/dependabot.yml +24 -2
  6. package/.github/scripts/check-markdown-links.ps1 +77 -0
  7. package/.github/scripts/check_markdown_links.py +89 -0
  8. package/.github/scripts/check_markdown_url_encoding.py +74 -0
  9. package/.github/scripts/validate_markdown_links.py +194 -0
  10. package/.github/workflows/csharpier-autofix.yml +152 -0
  11. package/.github/workflows/format-on-demand.yml +305 -0
  12. package/.github/workflows/lint-doc-links.yml +8 -5
  13. package/.github/workflows/markdown-json.yml +6 -2
  14. package/.github/workflows/npm-publish.yml +1 -1
  15. package/.github/workflows/prettier-autofix.yml +195 -0
  16. package/.github/workflows/update-dotnet-tools.yml +80 -0
  17. package/.github/workflows/yaml-format-lint.yml +41 -0
  18. package/.lychee.toml +4 -4
  19. package/.markdownlint.jsonc +21 -0
  20. package/.pre-commit-config.yaml +11 -3
  21. package/.yamllint.yaml +31 -0
  22. package/AGENTS.md +5 -1
  23. package/Docs/CHANGELOG.md +11 -0
  24. package/Docs/CONTRIBUTING.md +49 -0
  25. package/Docs/CONTRIBUTING.md.meta +7 -0
  26. package/{EDITOR_TOOLS_GUIDE.md → Docs/EDITOR_TOOLS_GUIDE.md} +4 -0
  27. package/Docs/EFFECTS_SYSTEM.md +1316 -0
  28. package/{EFFECTS_SYSTEM_TUTORIAL.md → Docs/EFFECTS_SYSTEM_TUTORIAL.md} +1 -1
  29. package/{GETTING_STARTED.md → Docs/GETTING_STARTED.md} +50 -64
  30. package/{GLOSSARY.md → Docs/GLOSSARY.md} +4 -4
  31. package/Docs/HELPER_UTILITIES.md +885 -0
  32. package/Docs/HELPER_UTILITIES.md.meta +7 -0
  33. package/{INDEX.md → Docs/INDEX.md} +107 -62
  34. package/Docs/MATH_AND_EXTENSIONS.md +1039 -0
  35. package/{RANDOM_PERFORMANCE.md → Docs/RANDOM_PERFORMANCE.md} +15 -15
  36. package/{RELATIONAL_COMPONENTS.md → Docs/RELATIONAL_COMPONENTS.md} +111 -84
  37. package/{SERIALIZATION.md → Docs/SERIALIZATION.md} +15 -0
  38. package/{SPATIAL_TREES_2D_GUIDE.md → Docs/SPATIAL_TREES_2D_GUIDE.md} +2 -2
  39. package/{SPATIAL_TREES_3D_GUIDE.md → Docs/SPATIAL_TREES_3D_GUIDE.md} +1 -1
  40. package/Docs/SPATIAL_TREE_2D_PERFORMANCE.md +241 -0
  41. package/Docs/SPATIAL_TREE_3D_PERFORMANCE.md +243 -0
  42. package/{THIRD_PARTY_NOTICES.md → Docs/THIRD_PARTY_NOTICES.md} +1 -1
  43. package/Docs/UTILITY_COMPONENTS.md +906 -0
  44. package/Docs/UTILITY_COMPONENTS.md.meta +7 -0
  45. package/Docs/VISUAL_COMPONENTS.md +337 -0
  46. package/Docs/VISUAL_COMPONENTS.md.meta +7 -0
  47. package/Editor/AnimationEventEditor.cs +337 -160
  48. package/Editor/Core/Helper/AnimationEventHelpers.cs +178 -152
  49. package/Editor/CustomEditors/PersistentDirectoryGUI.cs +20 -11
  50. package/Editor/CustomEditors/TexturePlatformOverrideEntryDrawer.cs +11 -2
  51. package/Editor/FitTextureSizeWindow.cs +43 -19
  52. package/Editor/PersistentDirectorySettings.cs +64 -12
  53. package/Editor/PrefabChecker.cs +72 -5
  54. package/Editor/Sprites/AnimationCopier.cs +131 -55
  55. package/Editor/Sprites/AnimationCreator.cs +63 -22
  56. package/Editor/Sprites/AnimationViewerWindow.cs +42 -6
  57. package/Editor/Sprites/TexturePlatformNameHelper.cs +50 -39
  58. package/Editor/Sprites/TextureResizerWizard.cs +23 -1
  59. package/Editor/Sprites/TextureSettingsApplierWindow.cs +148 -85
  60. package/Editor/Tools/ImageBlurTool.cs +81 -10
  61. package/Editor/Utils/EditorUi.cs +1 -1
  62. package/Editor/Utils/ScriptableObjectSingletonCreator.cs +1 -1
  63. package/README.md +428 -2433
  64. package/Runtime/AssemblyInfo.cs +4 -0
  65. package/Runtime/Core/Attributes/NotNullAttribute.cs +1 -3
  66. package/Runtime/Core/Attributes/RelationalComponentAssigner.cs +50 -5
  67. package/Runtime/Core/DataStructure/CyclicBuffer.cs +0 -1
  68. package/Runtime/Core/DataStructure/KDTree3D.cs +1 -1
  69. package/Runtime/Core/DataStructure/OctTree3D.cs +1 -1
  70. package/Runtime/Core/Extension/AsyncOperationExtensions.cs +122 -0
  71. package/Runtime/Core/Extension/RandomExtensions.cs +68 -0
  72. package/Runtime/Core/Extension/WallstopStudiosLogger.cs +16 -0
  73. package/Runtime/Core/Helper/Partials/ObjectHelpers.cs +4 -1
  74. package/Runtime/Core/Helper/ReflectionHelpers.cs +21 -10
  75. package/Runtime/Core/Helper/SpriteHelpers.cs +3 -1
  76. package/Runtime/Core/Helper/UnityMainThreadDispatcher.cs +45 -1
  77. package/Runtime/Core/Serialization/JsonConverters/GameObjectConverter.cs +13 -5
  78. package/Runtime/Core/Serialization/JsonConverters/ResolutionConverter.cs +1 -1
  79. package/Runtime/Core/Serialization/JsonConverters/TypeConverter.cs +1 -1
  80. package/Runtime/Core/Serialization/ProtobufUnitySurrogates.cs +24 -29
  81. package/Runtime/Core/Serialization/Serializer.cs +101 -0
  82. package/Runtime/Integrations/Reflex/AssemblyInfo.cs +7 -0
  83. package/Runtime/Integrations/Reflex/AssemblyInfo.cs.meta +11 -0
  84. package/Runtime/Integrations/Reflex/ContainerRelationalExtensions.cs +198 -0
  85. package/Runtime/Integrations/Reflex/ContainerRelationalExtensions.cs.meta +11 -0
  86. package/Runtime/Integrations/Reflex/RelationalComponentsInstaller.cs +86 -0
  87. package/Runtime/Integrations/Reflex/RelationalComponentsInstaller.cs.meta +11 -0
  88. package/Runtime/Integrations/Reflex/RelationalReflexSceneBootstrapper.cs +316 -0
  89. package/Runtime/Integrations/Reflex/RelationalReflexSceneBootstrapper.cs.meta +11 -0
  90. package/Runtime/Integrations/Reflex/RelationalSceneAssignmentOptions.cs +86 -0
  91. package/Runtime/Integrations/Reflex/RelationalSceneAssignmentOptions.cs.meta +11 -0
  92. package/Runtime/Integrations/Reflex/WallstopStudios.UnityHelpers.Integration.Reflex.asmdef +20 -0
  93. package/Runtime/Integrations/Reflex/WallstopStudios.UnityHelpers.Integration.Reflex.asmdef.meta +7 -0
  94. package/Runtime/Integrations/Reflex.meta +8 -0
  95. package/Runtime/Integrations/VContainer/AssemblyInfo.cs +9 -0
  96. package/Runtime/Integrations/VContainer/AssemblyInfo.cs.meta +3 -0
  97. package/Runtime/Integrations/VContainer/ObjectResolverRelationalExtensions.cs +96 -0
  98. package/Runtime/Integrations/VContainer/RelationalComponentEntryPoint.cs +90 -10
  99. package/Runtime/Integrations/VContainer/RelationalComponentsBuilderExtensions.cs +13 -1
  100. package/Runtime/Integrations/VContainer/RelationalObjectPools.cs +114 -0
  101. package/Runtime/Integrations/VContainer/RelationalObjectPools.cs.meta +11 -0
  102. package/Runtime/Integrations/VContainer/RelationalSceneAssignmentOptions.cs +16 -4
  103. package/Runtime/Integrations/VContainer/RelationalSceneLoadListener.cs +241 -0
  104. package/Runtime/Integrations/VContainer/RelationalSceneLoadListener.cs.meta +11 -0
  105. package/Runtime/Integrations/Zenject/AssemblyInfo.cs +9 -0
  106. package/Runtime/Integrations/Zenject/AssemblyInfo.cs.meta +3 -0
  107. package/Runtime/Integrations/Zenject/DiContainerRelationalExtensions.cs +69 -2
  108. package/Runtime/Integrations/Zenject/RelationalComponentSceneInitializer.cs +89 -12
  109. package/Runtime/Integrations/Zenject/RelationalComponentsInstaller.cs +23 -1
  110. package/Runtime/Integrations/Zenject/RelationalMemoryPools.cs +44 -0
  111. package/Runtime/Integrations/Zenject/RelationalMemoryPools.cs.meta +11 -0
  112. package/Runtime/Integrations/Zenject/RelationalSceneAssignmentOptions.cs +16 -10
  113. package/Runtime/Integrations/Zenject/RelationalSceneLoadListener.cs +243 -0
  114. package/Runtime/Integrations/Zenject/RelationalSceneLoadListener.cs.meta +11 -0
  115. package/Runtime/Tags/AttributeMetadataCache.cs +1 -4
  116. package/Runtime/Utils/Buffers.cs +4 -4
  117. package/Runtime/Utils/ScriptableObjectSingleton.cs +1 -2
  118. package/Runtime/Utils/SetTextureImportData.cs +3 -1
  119. package/Runtime/Utils/TextureScale.cs +10 -2
  120. package/Runtime/Visuals/UGUI/EnhancedImage.cs +6 -0
  121. package/Runtime/Visuals/UIToolkit/LayeredImage.cs +4 -1
  122. package/Samples~/DI - Reflex/README.md +527 -0
  123. package/Samples~/DI - Reflex/README.md.meta +7 -0
  124. package/Samples~/DI - Reflex/Scripts/ReflexPaletteService.cs +36 -0
  125. package/Samples~/DI - Reflex/Scripts/ReflexPaletteService.cs.meta +11 -0
  126. package/Samples~/DI - Reflex/Scripts/ReflexRelationalConsumer.cs +79 -0
  127. package/Samples~/DI - Reflex/Scripts/ReflexRelationalConsumer.cs.meta +11 -0
  128. package/Samples~/DI - Reflex/Scripts/ReflexSampleInstaller.cs +30 -0
  129. package/Samples~/DI - Reflex/Scripts/ReflexSampleInstaller.cs.meta +11 -0
  130. package/Samples~/DI - Reflex/Scripts/ReflexSpawner.cs +79 -0
  131. package/Samples~/DI - Reflex/Scripts/ReflexSpawner.cs.meta +11 -0
  132. package/Samples~/DI - Reflex/Scripts/Samples.UnityHelpers.DI.Reflex.asmdef +26 -0
  133. package/Samples~/DI - Reflex/Scripts/Samples.UnityHelpers.DI.Reflex.asmdef.meta +9 -0
  134. package/Samples~/DI - Reflex/Scripts.meta +8 -0
  135. package/Samples~/DI - Reflex.meta +8 -0
  136. package/Samples~/DI - VContainer/README.md +238 -56
  137. package/Samples~/DI - VContainer/Scripts/GameLifetimeScope.cs +22 -4
  138. package/Samples~/DI - VContainer/Scripts/RelationalConsumer.cs +5 -2
  139. package/Samples~/DI - VContainer/Scripts/Spawner.cs +113 -4
  140. package/Samples~/DI - Zenject/README.md +223 -58
  141. package/Samples~/DI - Zenject/Scripts/RelationalConsumer.cs +3 -0
  142. package/Samples~/DI - Zenject/Scripts/RelationalConsumerPool.cs +37 -0
  143. package/Samples~/DI - Zenject/Scripts/RelationalConsumerPool.cs.meta +12 -0
  144. package/Samples~/DI - Zenject/Scripts/SpawnerZenject.cs +74 -3
  145. package/Samples~/Random - PRNG/README.md +2 -1
  146. package/Samples~/Relational Components - Basic/README.md +3 -1
  147. package/Samples~/Serialization - JSON/README.md +2 -1
  148. package/Samples~/Spatial Structures - 2D and 3D/README.md +2 -1
  149. package/Samples~/UGUI - EnhancedImage/README.md +2 -1
  150. package/Samples~/UI Toolkit - MultiFile Selector (Editor)/README.md +2 -1
  151. package/Tests/Editor/Attributes/AnimationEventHelpersTests.cs +16 -0
  152. package/Tests/Editor/Core/Attributes/RelationalComponentAssignerTests.cs +32 -34
  153. package/Tests/Editor/Integrations/Reflex/ReflexIntegrationCompilationTests.cs +41 -0
  154. package/Tests/Editor/Integrations/Reflex/ReflexIntegrationCompilationTests.cs.meta +11 -0
  155. package/Tests/Editor/Integrations/Reflex/WallstopStudios.UnityHelpers.Tests.Editor.Reflex.asmdef +27 -0
  156. package/Tests/Editor/Integrations/Reflex/WallstopStudios.UnityHelpers.Tests.Editor.Reflex.asmdef.meta +7 -0
  157. package/Tests/Editor/Integrations/Reflex.meta +8 -0
  158. package/Tests/Editor/Integrations/VContainer/VContainerRelationalEntryPointTests.cs +21 -18
  159. package/Tests/Editor/Integrations/VContainer/VContainerRelationalHelpersTests.cs +164 -0
  160. package/Tests/Editor/Integrations/VContainer/VContainerRelationalHelpersTests.cs.meta +11 -0
  161. package/Tests/Editor/Integrations/VContainer/WallstopStudios.UnityHelpers.Tests.Editor.VContainer.asmdef +2 -1
  162. package/Tests/Editor/Integrations/Zenject/WallstopStudios.UnityHelpers.Tests.Editor.Zenject.asmdef +3 -2
  163. package/Tests/Editor/Integrations/Zenject/ZenjectRelationalHelpersTests.cs +127 -0
  164. package/Tests/Editor/Integrations/Zenject/ZenjectRelationalHelpersTests.cs.meta +11 -0
  165. package/Tests/Editor/Integrations/Zenject/ZenjectRelationalInitializerTests.cs +25 -23
  166. package/Tests/Editor/PersistentDirectorySettingsTests.cs +58 -0
  167. package/Tests/Editor/PersistentDirectorySettingsTests.cs.meta +11 -0
  168. package/Tests/Editor/PrefabCheckerReportTests.cs +32 -0
  169. package/Tests/Editor/PrefabCheckerReportTests.cs.meta +11 -0
  170. package/Tests/Editor/Sprites/AnimationCopierFilterTests.cs +63 -0
  171. package/Tests/Editor/Sprites/AnimationCopierFilterTests.cs.meta +11 -0
  172. package/Tests/Editor/Sprites/AnimationCopierWindowTests.cs +1 -1
  173. package/Tests/Editor/Sprites/AnimationViewerWindowTests.cs +38 -0
  174. package/Tests/Editor/Sprites/AnimationViewerWindowTests.cs.meta +11 -0
  175. package/Tests/Editor/Sprites/ScriptableSpriteAtlasEditorTests.cs +1 -1
  176. package/Tests/Editor/Sprites/SpriteCropperAdditionalTests.cs +12 -12
  177. package/Tests/Editor/Sprites/SpriteCropperTests.cs +9 -9
  178. package/Tests/Editor/Sprites/SpritePivotAdjusterTests.cs +3 -3
  179. package/Tests/Editor/Sprites/TexturePlatformNameHelperTests.cs +18 -0
  180. package/Tests/Editor/Sprites/TextureResizerWizardTests.cs +5 -5
  181. package/Tests/Editor/Sprites/TextureSettingsApplierAPITests.cs +3 -3
  182. package/Tests/Editor/Sprites/TextureSettingsApplierWizardAdditionalTests.cs +4 -4
  183. package/Tests/Editor/Sprites/TextureSettingsApplierWizardTests.cs +4 -4
  184. package/Tests/Editor/Tools/ImageBlurToolTests.cs +22 -110
  185. package/Tests/Editor/Utils/CommonTestBase.cs +60 -1
  186. package/Tests/Editor/Utils/ScriptableObjectSingletonCreatorTests.cs +6 -6
  187. package/Tests/Editor/Windows/FitTextureSizeWindowTests.cs +66 -74
  188. package/Tests/Runtime/Attributes/RelationalComponentInitializerTests.cs +4 -15
  189. package/Tests/Runtime/DataStructures/SpatialTree3DBoundsConsistencyTests.cs +29 -29
  190. package/Tests/Runtime/Extensions/AsyncOperationExtensionsTests.cs +179 -0
  191. package/Tests/Runtime/Extensions/RandomExtensionTests.cs +55 -0
  192. package/Tests/Runtime/Integrations/Reflex/RelationalComponentsReflexTests.cs +445 -0
  193. package/Tests/Runtime/Integrations/Reflex/RelationalComponentsReflexTests.cs.meta +11 -0
  194. package/Tests/Runtime/Integrations/Reflex/WallstopStudios.UnityHelpers.Tests.Runtime.Reflex.asmdef +28 -0
  195. package/Tests/Runtime/Integrations/Reflex/WallstopStudios.UnityHelpers.Tests.Runtime.Reflex.asmdef.meta +7 -0
  196. package/Tests/Runtime/Integrations/Reflex.meta +8 -0
  197. package/Tests/Runtime/Integrations/VContainer/RelationalComponentsVContainerTests.cs +257 -221
  198. package/Tests/Runtime/Integrations/VContainer/RelationalObjectPoolsVContainerTests.cs +91 -0
  199. package/Tests/Runtime/Integrations/VContainer/RelationalObjectPoolsVContainerTests.cs.meta +11 -0
  200. package/Tests/Runtime/Integrations/Zenject/RelationalComponentsZenjectTests.cs +251 -233
  201. package/Tests/Runtime/Performance/RandomPerformanceTests.cs +1 -1
  202. package/Tests/Runtime/Performance/SpatialTree2DPerformanceTests.cs +6 -1
  203. package/Tests/Runtime/Performance/SpatialTree3DPerformanceTests.cs +4 -1
  204. package/Tests/Runtime/Serialization/JsonConverterAdditionalTests.cs +30 -0
  205. package/Tests/Runtime/Serialization/JsonConverterAdditionalTests.cs.meta +11 -0
  206. package/Tests/Runtime/Serialization/JsonConverterTests.cs +8 -12
  207. package/Tests/Runtime/Serialization/JsonRoundtripComprehensiveTests.cs +4 -9
  208. package/Tests/Runtime/Serialization/JsonSerializationTest.cs +16 -5
  209. package/Tests/Runtime/Serialization/ProtoRoundtripComprehensiveTests.cs +13 -13
  210. package/Tests/Runtime/Serialization/SerializerAdditionalTests.cs +12 -0
  211. package/Tests/Runtime/Serialization/SerializerFileIoTests.cs +105 -0
  212. package/Tests/Runtime/Serialization/SerializerFileIoTests.cs.meta +11 -0
  213. package/Tests/Runtime/Serialization/UnityEngineObjectJsonTests.cs +247 -0
  214. package/Tests/Runtime/Serialization/UnityEngineObjectJsonTests.cs.meta +11 -0
  215. package/Tests/Runtime/TestUtils/CommonTestBase.cs +99 -0
  216. package/Tests/Runtime/TestUtils/ReflexTestSupport.cs +111 -0
  217. package/Tests/Runtime/TestUtils/ReflexTestSupport.cs.meta +12 -0
  218. package/Tests/Runtime/Utils/CoroutineHandlerTests.cs +1 -1
  219. package/Tests/Runtime/Utils/LZMAComprehensiveTests.cs +1 -1
  220. package/Tests/Runtime/Utils/LZMATests.cs +1 -1
  221. package/Tests/Runtime/Utils/MatchColliderToSpriteTests.cs +5 -5
  222. package/Tests/Runtime/Visuals/EnhancedImageTests.cs +25 -56
  223. package/Tests/Runtime/Visuals/VisualsTestHelpers.cs +1 -8
  224. package/Tests/TestUtils.meta +8 -0
  225. package/package-lock.json.meta +7 -0
  226. package/package.json +13 -4
  227. package/scripts/check-eol.ps1 +4 -5
  228. package/scripts/lint-tests.ps1 +156 -0
  229. package/scripts/lint-tests.ps1.meta +7 -0
  230. package/scripts/normalize-eol.ps1 +6 -9
  231. package/.github/workflows/csharpier.yml +0 -135
  232. package/CHANGELOG.md +0 -0
  233. package/EFFECTS_SYSTEM.md +0 -242
  234. package/MATH_AND_EXTENSIONS.md +0 -316
  235. package/SPATIAL_TREE_2D_PERFORMANCE.md +0 -238
  236. package/SPATIAL_TREE_3D_PERFORMANCE.md +0 -240
  237. /package/{CHANGELOG.md.meta → Docs/CHANGELOG.md.meta} +0 -0
  238. /package/{DATA_STRUCTURES.md → Docs/DATA_STRUCTURES.md} +0 -0
  239. /package/{DATA_STRUCTURES.md.meta → Docs/DATA_STRUCTURES.md.meta} +0 -0
  240. /package/{EDITOR_TOOLS_GUIDE.md.meta → Docs/EDITOR_TOOLS_GUIDE.md.meta} +0 -0
  241. /package/{EFFECTS_SYSTEM.md.meta → Docs/EFFECTS_SYSTEM.md.meta} +0 -0
  242. /package/{EFFECTS_SYSTEM_TUTORIAL.md.meta → Docs/EFFECTS_SYSTEM_TUTORIAL.md.meta} +0 -0
  243. /package/{GETTING_STARTED.md.meta → Docs/GETTING_STARTED.md.meta} +0 -0
  244. /package/{GLOSSARY.md.meta → Docs/GLOSSARY.md.meta} +0 -0
  245. /package/{HULLS.md → Docs/HULLS.md} +0 -0
  246. /package/{HULLS.md.meta → Docs/HULLS.md.meta} +0 -0
  247. /package/{INDEX.md.meta → Docs/INDEX.md.meta} +0 -0
  248. /package/{LICENSE.md → Docs/LICENSE.md} +0 -0
  249. /package/{LICENSE.md.meta → Docs/LICENSE.md.meta} +0 -0
  250. /package/{MATH_AND_EXTENSIONS.md.meta → Docs/MATH_AND_EXTENSIONS.md.meta} +0 -0
  251. /package/{RANDOM_PERFORMANCE.md.meta → Docs/RANDOM_PERFORMANCE.md.meta} +0 -0
  252. /package/{REFLECTION_HELPERS.md → Docs/REFLECTION_HELPERS.md} +0 -0
  253. /package/{REFLECTION_HELPERS.md.meta → Docs/REFLECTION_HELPERS.md.meta} +0 -0
  254. /package/{RELATIONAL_COMPONENTS.md.meta → Docs/RELATIONAL_COMPONENTS.md.meta} +0 -0
  255. /package/{SERIALIZATION.md.meta → Docs/SERIALIZATION.md.meta} +0 -0
  256. /package/{SINGLETONS.md → Docs/SINGLETONS.md} +0 -0
  257. /package/{SINGLETONS.md.meta → Docs/SINGLETONS.md.meta} +0 -0
  258. /package/{SPATIAL_TREES_2D_GUIDE.md.meta → Docs/SPATIAL_TREES_2D_GUIDE.md.meta} +0 -0
  259. /package/{SPATIAL_TREES_3D_GUIDE.md.meta → Docs/SPATIAL_TREES_3D_GUIDE.md.meta} +0 -0
  260. /package/{SPATIAL_TREE_2D_PERFORMANCE.md.meta → Docs/SPATIAL_TREE_2D_PERFORMANCE.md.meta} +0 -0
  261. /package/{SPATIAL_TREE_3D_PERFORMANCE.md.meta → Docs/SPATIAL_TREE_3D_PERFORMANCE.md.meta} +0 -0
  262. /package/{SPATIAL_TREE_SEMANTICS.md → Docs/SPATIAL_TREE_SEMANTICS.md} +0 -0
  263. /package/{SPATIAL_TREE_SEMANTICS.md.meta → Docs/SPATIAL_TREE_SEMANTICS.md.meta} +0 -0
  264. /package/{THIRD_PARTY_NOTICES.md.meta → Docs/THIRD_PARTY_NOTICES.md.meta} +0 -0
@@ -81,18 +81,18 @@ This document contains performance benchmarks for the various random number gene
81
81
 
82
82
  | Random | NextBool | Next | NextUInt | NextFloat | NextDouble | NextUint - Range | NextInt - Range |
83
83
  | --------------------------- | ----------- | ----------- | ------------- | ----------- | ----------- | ---------------- | --------------- |
84
- | DotNetRandom | 548,300,000 | 54,900,000 | 58,300,000 | 48,000,000 | 28,100,000 | 54,800,000 | 54,100,000 |
85
- | LinearCongruentialGenerator | 805,700,000 | 829,700,000 | 1,334,700,000 | 212,300,000 | 411,000,000 | 558,500,000 | 503,400,000 |
86
- | IllusionFlow | 787,300,000 | 655,900,000 | 885,100,000 | 203,500,000 | 309,000,000 | 442,200,000 | 392,100,000 |
87
- | PcgRandom | 793,900,000 | 662,100,000 | 919,300,000 | 211,700,000 | 341,200,000 | 453,800,000 | 407,700,000 |
88
- | RomuDuo | 796,900,000 | 556,300,000 | 707,100,000 | 189,500,000 | 254,800,000 | 423,300,000 | 390,900,000 |
89
- | SplitMix64 | 803,400,000 | 739,200,000 | 1,063,900,000 | 212,600,000 | 381,300,000 | 485,700,000 | 439,400,000 |
90
- | SquirrelRandom | 781,900,000 | 394,900,000 | 413,800,000 | 198,000,000 | 203,400,000 | 365,900,000 | 311,700,000 |
91
- | SystemRandom | 143,400,000 | 148,500,000 | 65,200,000 | 131,400,000 | 137,200,000 | 59,000,000 | 60,000,000 |
92
- | UnityRandom | 657,500,000 | 85,000,000 | 87,800,000 | 65,200,000 | 41,500,000 | 81,500,000 | 82,200,000 |
93
- | WyRandom | 771,400,000 | 389,300,000 | 456,500,000 | 183,500,000 | 194,200,000 | 297,000,000 | 282,100,000 |
94
- | XorShiftRandom | 796,600,000 | 563,800,000 | 603,100,000 | 212,800,000 | 286,800,000 | 481,000,000 | 392,200,000 |
95
- | XoroShiroRandom | 793,500,000 | 557,600,000 | 712,900,000 | 190,200,000 | 244,000,000 | 428,100,000 | 379,800,000 |
84
+ | DotNetRandom | 550,600,000 | 53,100,000 | 57,400,000 | 45,600,000 | 26,900,000 | 53,700,000 | 53,900,000 |
85
+ | LinearCongruentialGenerator | 814,800,000 | 538,900,000 | 1,335,100,000 | 184,700,000 | 296,500,000 | 591,500,000 | 508,400,000 |
86
+ | IllusionFlow | 800,200,000 | 489,500,000 | 892,600,000 | 167,600,000 | 268,200,000 | 444,600,000 | 396,100,000 |
87
+ | PcgRandom | 796,400,000 | 537,900,000 | 889,500,000 | 184,300,000 | 291,400,000 | 456,500,000 | 412,000,000 |
88
+ | RomuDuo | 794,300,000 | 359,300,000 | 766,200,000 | 167,200,000 | 191,600,000 | 446,000,000 | 397,600,000 |
89
+ | SplitMix64 | 801,100,000 | 537,400,000 | 972,300,000 | 183,800,000 | 296,600,000 | 487,500,000 | 446,600,000 |
90
+ | SquirrelRandom | 747,700,000 | 383,300,000 | 413,800,000 | 172,300,000 | 204,800,000 | 330,200,000 | 314,200,000 |
91
+ | SystemRandom | 146,800,000 | 148,300,000 | 65,700,000 | 132,500,000 | 139,500,000 | 59,800,000 | 61,300,000 |
92
+ | UnityRandom | 647,700,000 | 77,800,000 | 87,800,000 | 62,100,000 | 39,500,000 | 81,500,000 | 82,400,000 |
93
+ | WyRandom | 750,700,000 | 382,900,000 | 447,500,000 | 166,800,000 | 191,700,000 | 296,800,000 | 281,100,000 |
94
+ | XorShiftRandom | 792,900,000 | 536,400,000 | 606,000,000 | 184,100,000 | 287,300,000 | 442,800,000 | 391,200,000 |
95
+ | XoroShiroRandom | 789,200,000 | 359,300,000 | 715,100,000 | 167,300,000 | 192,500,000 | 428,900,000 | 383,500,000 |
96
96
 
97
97
  <!-- RANDOM_BENCHMARKS_END -->
98
98
 
@@ -124,13 +124,13 @@ All benchmarks are run for 1 second per operation type to ensure statistical sig
124
124
  **Core Guides:**
125
125
 
126
126
  - [Getting Started](GETTING_STARTED.md) - Your first 5 minutes with Unity Helpers
127
- - [Main README](README.md) - Complete feature overview
127
+ - [Main README](../README.md) - Complete feature overview
128
128
  - [Feature Index](INDEX.md) - Alphabetical reference
129
129
 
130
130
  **Random Number Generator Features:**
131
131
 
132
- - [README - Random Generators](README.md#random-number-generators) - Full API reference
133
- - [README - Quick Start](README.md#random-number-generation) - 60-second tutorial
132
+ - [README - Random Generators](../README.md#random-number-generators) - Full API reference
133
+ - [README - Quick Start](../README.md#random-number-generation) - 60-second tutorial
134
134
 
135
135
  **Related Features:**
136
136
 
@@ -314,114 +314,120 @@ Notes:
314
314
 
315
315
  ## Dependency Injection Integrations
316
316
 
317
- Unity Helpers provides optional integration assemblies that only compile when Zenject or VContainer is present in your project. Install the corresponding DI package via the Unity Package Manager and the helpers become available automatically (no additional scripting defines required).
317
+ **Stop choosing between DI and clean hierarchy references** - Unity Helpers provides seamless integrations with Zenject/Extenject, VContainer, and Reflex that automatically wire up your relational component fields right after dependency injection completes.
318
318
 
319
- Why use the DI integrations
319
+ ### The DI Pain Point
320
320
 
321
- - Eliminate boilerplate: hydrate relational fields after DI injection automatically.
322
- - Consistent behavior: integrates with constructor/property injection and works with runtime instantiation.
323
- - Safe fallback: if the DI binding is missing, falls back to the non-DI path so fields still populate.
321
+ Without these integrations, you're stuck writing `Awake()` methods full of `GetComponent` boilerplate **even when using a DI framework**:
324
322
 
325
- Supported package IDs (auto-detected)
326
-
327
- - Zenject/Extenject: `com.extenject.zenject`, `com.modesttree.zenject`, `com.svermeulen.extenject`
328
- - VContainer: `jp.cysharp.vcontainer`, `jp.hadashikick.vcontainer`
323
+ ```csharp
324
+ public class Enemy : MonoBehaviour
325
+ {
326
+ [Inject] private IHealthSystem _health; // ✅ DI handles this
329
327
 
330
- Manual or source imports (no UPM)
328
+ private Animator _animator; // Still manual boilerplate
329
+ private Rigidbody2D _rigidbody; // ❌ Still manual boilerplate
331
330
 
332
- - If you import Zenject/VContainer as source, a .unitypackage, or a plain DLL, Unity cannot infer package IDs and the `versionDefines` in the asmdefs won’t trigger.
333
- - Add scripting defines in Project Settings to enable the integrations:
334
- - `Project Settings > Player > Other Settings > Scripting Define Symbols`
335
- - Add `ZENJECT_PRESENT` when Zenject/Extenject is present and/or `VCONTAINER_PRESENT` when VContainer is present.
336
- - Set defines per target platform (Standalone, Android, iOS, etc.).
337
- - After adding, Unity recompiles and the optional assemblies under `Runtime/Integrations/*` compile automatically.
331
+ void Awake()
332
+ {
333
+ _animator = GetComponent<Animator>();
334
+ _rigidbody = GetComponent<Rigidbody2D>();
335
+ // ... 15 more lines of GetComponent hell
336
+ }
337
+ }
338
+ ```
338
339
 
339
- ### Quick Start — VContainer
340
+ ### The Integration Solution
340
341
 
341
- 1. Register integration in your `LifetimeScope`
342
+ With the DI integrations, **everything just works**:
342
343
 
343
344
  ```csharp
344
- using VContainer;
345
- using VContainer.Unity;
346
- using WallstopStudios.UnityHelpers.Integrations.VContainer;
347
-
348
- public sealed class GameLifetimeScope : LifetimeScope
345
+ public class Enemy : MonoBehaviour
349
346
  {
350
- protected override void Configure(IContainerBuilder builder)
351
- {
352
- // Registers IRelationalComponentAssigner and a scene entry point
353
- builder.RegisterRelationalComponents();
347
+ [Inject] private IHealthSystem _health; // ✅ DI injection
348
+ [SiblingComponent] private Animator _animator; // ✅ Relational auto-wiring
349
+ [SiblingComponent] private Rigidbody2D _rigidbody; // Relational auto-wiring
354
350
 
355
- // Or customize scanning (active objects only)
356
- // builder.RegisterRelationalComponents(new RelationalSceneAssignmentOptions(includeInactive: false));
357
- }
351
+ // No Awake() needed! Both DI and hierarchy references wired automatically
358
352
  }
359
353
  ```
360
354
 
361
- 1. Build up runtime instances (DI + relational fields)
355
+ ### Why Use the DI Integrations
362
356
 
363
- ```csharp
364
- using UnityEngine;
365
- using VContainer;
366
- using WallstopStudios.UnityHelpers.Integrations.VContainer;
357
+ - **Zero boilerplate** - No `Awake()` method needed, no manual `GetComponent` calls, no validation code
358
+ - **Consistent behavior** - Works seamlessly with constructor/property/field injection and runtime instantiation
359
+ - **Safe fallback** - Gracefully degrades to standard behavior if DI binding is missing
360
+ - **Risk-free adoption** - Use incrementally, mix DI and non-DI components freely
367
361
 
368
- public sealed class Spawner : MonoBehaviour
369
- {
370
- [Inject] private IObjectResolver _resolver;
371
- [SerializeField] private Enemy _enemyPrefab;
362
+ ### Supported Packages (Auto-detected)
372
363
 
373
- public Enemy Spawn(Transform parent)
374
- {
375
- Enemy enemy = Instantiate(_enemyPrefab, parent);
376
- return _resolver.BuildUpWithRelations(enemy);
377
- }
378
- }
379
- ```
364
+ Unity Helpers automatically detects these packages via UPM:
380
365
 
381
- 1. Apply to whole hierarchies when needed
366
+ - **Zenject/Extenject**: `com.extenject.zenject`, `com.modesttree.zenject`, `com.svermeulen.extenject`
367
+ - **VContainer**: `jp.cysharp.vcontainer`, `jp.hadashikick.vcontainer`
368
+ - **Reflex**: `com.gustavopsantos.reflex`
382
369
 
383
- ```csharp
384
- _resolver.AssignRelationalHierarchy(root, includeInactiveChildren: false);
385
- ```
370
+ > 💡 **UPM packages work out-of-the-box** - No scripting defines needed!
386
371
 
387
- ### Quick Start Zenject
372
+ ### Manual or Source Imports (Non-UPM)
388
373
 
389
- 1. Add the installer to your SceneContext
374
+ If you import Zenject/VContainer/Reflex as source code, .unitypackage, or raw DLLs (not via UPM), you need to manually add scripting defines:
390
375
 
391
- - Add a `SceneContext` to your scene.
392
- - Add `RelationalComponentsInstaller` to the same GameObject.
393
- - Toggle "Assign Scene On Initialize" to run a one-time scene scan after the container builds.
376
+ 1. Open `Project Settings > Player > Other Settings > Scripting Define Symbols`
377
+ 2. Add the appropriate define(s) for your target platforms:
378
+ - `ZENJECT_PRESENT` - When using Zenject/Extenject
379
+ - `VCONTAINER_PRESENT` - When using VContainer
380
+ - `REFLEX_PRESENT` - When using Reflex
381
+ 3. Unity will recompile and the integration assemblies under `Runtime/Integrations/*` will activate automatically
394
382
 
395
- 1. Instantiate prefabs with DI + relational assignment
383
+ ### VContainer at a Glance
396
384
 
397
- ```csharp
398
- using UnityEngine;
399
- using Zenject;
400
- using WallstopStudios.UnityHelpers.Integrations.Zenject;
385
+ - **Enable once per scope**
401
386
 
402
- public sealed class Spawner
403
- {
404
- readonly DiContainer _container;
405
- readonly Enemy _enemyPrefab;
387
+ ```csharp
388
+ builder.RegisterRelationalComponents(
389
+ new RelationalSceneAssignmentOptions(includeInactive: true, useSinglePassScan: true),
390
+ enableAdditiveSceneListener: true
391
+ );
392
+ ```
406
393
 
407
- public Spawner(DiContainer container, Enemy enemyPrefab)
408
- {
409
- _container = container;
410
- _enemyPrefab = enemyPrefab;
411
- }
394
+ - **Runtime helpers**
395
+ - `_resolver.InstantiateComponentWithRelations(componentPrefab, parent)`
396
+ - `_resolver.InstantiateGameObjectWithRelations(rootPrefab, parent, includeInactiveChildren: true)`
397
+ - `_resolver.AssignRelationalHierarchy(existingRoot, includeInactiveChildren: true)`
398
+ - `RelationalObjectPools.CreatePoolWithRelations(...)` + `pool.GetWithRelations(resolver)`
412
399
 
413
- public Enemy Spawn(Transform parent)
414
- {
415
- return _container.InstantiateComponentWithRelations(_enemyPrefab, parent);
416
- }
417
- }
418
- ```
400
+ - **Full walkthrough**: [DI – VContainer sample](Samples~/DI%20-%20VContainer/README.md)
419
401
 
420
- 1. Apply to whole hierarchies
402
+ ### Zenject at a Glance
421
403
 
422
- ```csharp
423
- Container.AssignRelationalHierarchy(root, includeInactiveChildren: true);
424
- ```
404
+ - **Install once per scene**
405
+ - Add `RelationalComponentsInstaller` to your `SceneContext`.
406
+ - Toggles cover include-inactive scanning, single-pass strategy, and additive-scene listening.
407
+
408
+ - **Runtime helpers**
409
+ - `_container.InstantiateComponentWithRelations(componentPrefab, parent)`
410
+ - `_container.InstantiateGameObjectWithRelations(rootPrefab, parent, includeInactiveChildren: true)`
411
+ - `_container.AssignRelationalHierarchy(existingRoot, includeInactiveChildren: true)`
412
+ - Subclass `RelationalMemoryPool<T>` to hydrate pooled items on spawn.
413
+
414
+ - **Full walkthrough**: [DI – Zenject sample](Samples~/DI%20-%20Zenject/README.md)
415
+
416
+ ### Reflex at a Glance
417
+
418
+ - **Install once per scene**
419
+ - Reflex creates a `SceneScope` in each scene. Add `RelationalComponentsInstaller` to the same GameObject (or a child) to bind the relational assigner, run the initial scene scan, and optionally register the additive-scene listener.
420
+ - Toggles mirror the runtime helpers: include inactive objects, choose scan strategy, and enable additive listening.
421
+
422
+ - **Runtime helpers**
423
+ - `_container.InjectWithRelations(existingComponent)` to inject DI fields and hydrate relational attributes on existing objects.
424
+ - `_container.InstantiateComponentWithRelations(componentPrefab, parent)` for component prefabs.
425
+ - `_container.InstantiateGameObjectWithRelations(rootPrefab, parent, includeInactiveChildren: true)` for full hierarchies.
426
+ - `_container.AssignRelationalHierarchy(existingRoot, includeInactiveChildren: true)` to hydrate arbitrary hierarchies after manual instantiation.
427
+
428
+ - **Full walkthrough**: [DI – Reflex sample](Samples~/DI%20-%20Reflex/README.md)
429
+
430
+ - Reflex shares the same fallback behaviour: if the assigner is not bound, the helpers call `AssignRelationalComponents()` directly so you can adopt incrementally.
425
431
 
426
432
  Notes
427
433
 
@@ -479,7 +485,21 @@ Beginner-friendly overview
479
485
 
480
486
  VContainer (1.16.x)
481
487
 
482
- - Runtime usage (LifetimeScope): Call `builder.RegisterRelationalComponents()` in `LifetimeScope.Configure`. The entry point runs automatically after the container builds.
488
+ - Runtime usage (LifetimeScope): Call `builder.RegisterRelationalComponents()` in `LifetimeScope.Configure`. The entry point runs automatically after the container builds. You can enable an additive-scene listener and customize scan options:
489
+
490
+ ```csharp
491
+ using VContainer;
492
+ using VContainer.Unity;
493
+ using WallstopStudios.UnityHelpers.Integrations.VContainer;
494
+
495
+ protected override void Configure(IContainerBuilder builder)
496
+ {
497
+ // Single-pass scan + additive scene listener
498
+ var options = new RelationalSceneAssignmentOptions(includeInactive: true, useSinglePassScan: true);
499
+ builder.RegisterRelationalComponents(options, enableAdditiveSceneListener: true);
500
+ }
501
+ ```
502
+
483
503
  - Tests without LifetimeScope: Construct the entry point and call `Initialize()` yourself, and register your `AttributeMetadataCache` instance so the assigner uses it:
484
504
 
485
505
  ```csharp
@@ -500,7 +520,8 @@ VContainer (1.16.x)
500
520
  entry.Initialize();
501
521
  ```
502
522
 
503
- - Inject vs BuildUp: Use `resolver.Inject(component)` before calling `resolver.AssignRelationalComponents(component)`.
523
+ - Inject vs BuildUp: Use `resolver.InjectWithRelations(component)` to inject + assign in one call, or `resolver.Inject(component)` then `resolver.AssignRelationalComponents(component)`.
524
+ - Prefabs & GameObjects: `resolver.InstantiateComponentWithRelations(prefab, parent)` or `resolver.InstantiateGameObjectWithRelations(prefab, parent)`; to inject existing hierarchies use `resolver.InjectGameObjectWithRelations(root)`.
504
525
 
505
526
  - EditMode reliability: In EditMode tests, prefer `[UnityTest]` and `yield return null` after creating objects and after initializing the entry point so Unity has a frame to register new objects before `FindObjectsOfType` runs and to allow assignments to complete.
506
527
  - Active scene filter: Entry points operate on the active scene only. In EditMode, create a new scene with `SceneManager.CreateScene`, set it active, and move your test hierarchy into it before calling `Initialize()`.
@@ -508,10 +529,16 @@ VContainer (1.16.x)
508
529
 
509
530
  Zenject/Extenject
510
531
 
511
- - Runtime usage: Add `RelationalComponentsInstaller` to your `SceneContext`. It binds `IRelationalComponentAssigner` and runs `RelationalComponentSceneInitializer` once the container is ready.
532
+ - Runtime usage: Add `RelationalComponentsInstaller` to your `SceneContext`. It binds `IRelationalComponentAssigner` and runs `RelationalComponentSceneInitializer` once the container is ready. The installer exposes toggles to assign on initialize and to listen for additive scenes.
512
533
  - Tests: Bind a concrete `AttributeMetadataCache` instance and construct the assigner with that cache. Then resolve `IInitializable` and call `Initialize()`.
513
534
  - EditMode reliability: As with VContainer, consider `[UnityTest]` with a `yield return null` after creating objects and after calling `Initialize()` to allow Unity to register objects and complete assignments.
514
- - Active scene filter: The initializer operates on the active scene only. Create and set an active scene and move your test hierarchy into it before calling `Initialize()`.
535
+ - Active scene filter: Initial one-time scan operates on the active scene only. The additive-scene listener processes only newly loaded scenes (not all loaded scenes).
536
+ - Prefabs & GameObjects: `container.InstantiateComponentWithRelations(...)`, `container.InstantiateGameObjectWithRelations(...)`, or `container.InjectGameObjectWithRelations(root)`; to inject + assign a single instance: `container.InjectWithRelations(component)`.
537
+
538
+ ### Object Pools (DI-aware)
539
+
540
+ - Zenject: use `RelationalMemoryPool<T>` (or `<TParam, T>`) to assign relational fields in `OnSpawned` automatically.
541
+ - VContainer: create pools with `RelationalObjectPools.CreatePoolWithRelations(...)` and rent via `pool.GetWithRelations(resolver)` to inject + assign.
515
542
 
516
543
  Common pitfalls and how to avoid them
517
544
 
@@ -526,7 +553,7 @@ Common pitfalls and how to avoid them
526
553
  **Core Guides:**
527
554
 
528
555
  - [Getting Started](GETTING_STARTED.md) - Your first 5 minutes with Unity Helpers
529
- - [Main README](README.md) - Complete feature overview
556
+ - [Main README](../README.md) - Complete feature overview
530
557
  - [Feature Index](INDEX.md) - Alphabetical reference
531
558
 
532
559
  **Related Features:**
@@ -646,3 +646,18 @@ References
646
646
  - Replace direct `System.Text.Json.JsonSerializer` calls in app code with `Serializer.JsonSerialize/JsonDeserialize/JsonStringify`, or with `Serializer.Serialize/Deserialize` + `SerializationType.Json` to centralize options and Unity converters.
647
647
  - Replace any custom protobuf helpers with `Serializer.ProtoSerialize/ProtoDeserialize` or the generic `Serializer.Serialize/Deserialize` APIs. Ensure models are annotated with `[ProtoContract]` and stable `[ProtoMember(n)]` tags.
648
648
  - For existing binary saves using BinaryFormatter, prefer migrating to Json or Protobuf. If you must keep BinaryFormatter, scope it to trusted, same-version caches only.
649
+
650
+ ## 2.0 changes
651
+
652
+ - BinaryFormatter (`SerializationType.SystemBinary`) is deprecated but remains functional for trusted/legacy scenarios. Prefer:
653
+ - `SerializationType.Json` (System.Text.Json with Unity-aware converters) for readable, diffable content.
654
+ - `SerializationType.Protobuf` (protobuf-net) for compact, high-performance binary payloads.
655
+
656
+ ## IL2CPP / AOT guidance
657
+
658
+ System.Text.Json can require extra care under AOT (e.g., IL2CPP):
659
+
660
+ - Prefer explicit `JsonSerializerOptions` and concrete generic APIs over `object`-based serialization to reduce reflection.
661
+ - For hot POCO models, consider adding a source-generated context (JsonSerializerContext) in your game assembly and pass it to `JsonSerializer` calls.
662
+ - If you rely on many custom converters, ensure they are referenced by code so the linker doesn't strip them. The UnityHelpers converters are referenced via options by default.
663
+ - Avoid deserializing `System.Type` from untrusted input (see `TypeConverter`); this is intended for trusted configs/tools.
@@ -177,7 +177,7 @@ void Update()
177
177
  }
178
178
  ```
179
179
 
180
- See [Buffering Pattern](README.md#buffering-pattern) for the complete guide and [Pooling Utilities](README.md#pooling-utilities) for more pooling options.
180
+ See [Buffering Pattern](../README.md#buffering-pattern) for the complete guide and [Pooling Utilities](../README.md#pooling-utilities) for more pooling options.
181
181
 
182
182
  ## Structures
183
183
 
@@ -247,7 +247,7 @@ START: Do your objects move frequently?
247
247
  - **Nearest neighbors on static points:** KDTree2D (Balanced)
248
248
  - **Fast builds with good-enough queries:** KDTree2D (Unbalanced)
249
249
  - **Objects with area; bounds queries primary:** RTree2D
250
- - **Very frequent movement (every frame):** SpatialHash2D (see [README](README.md#choosing-spatial-structures))
250
+ - **Very frequent movement (every frame):** SpatialHash2D (see [README](../README.md#choosing-spatial-structures))
251
251
 
252
252
  ## Query Semantics
253
253
 
@@ -167,7 +167,7 @@ void Update()
167
167
  }
168
168
  ```
169
169
 
170
- See [Buffering Pattern](README.md#buffering-pattern) for the complete guide and [Pooling Utilities](README.md#pooling-utilities) for more pooling options.
170
+ See [Buffering Pattern](../README.md#buffering-pattern) for the complete guide and [Pooling Utilities](../README.md#pooling-utilities) for more pooling options.
171
171
 
172
172
  ## Structures
173
173
 
@@ -0,0 +1,241 @@
1
+ # 2D Spatial Tree Performance Benchmarks
2
+
3
+ ## TL;DR — What Problem This Solves
4
+
5
+ - Fast range/bounds/nearest‑neighbor queries on 2D data without scanning everything.
6
+ - Quick picks: QuadTree2D for broad‑phase; KDTree2D (Balanced) for NN; KDTree2D (Unbalanced) for fast rebuilds; RTree2D for bounds‑based data.
7
+
8
+ This document contains performance benchmarks for the 2D spatial tree implementations in Unity Helpers.
9
+
10
+ ## Available 2D Spatial Trees
11
+
12
+ - **QuadTree2D** - Easiest to use, good all-around performance
13
+ - **KDTree2D** - Balanced and unbalanced variants available
14
+ - **RTree2D** - Optimized for bounding box queries
15
+
16
+ ### Correctness & Semantics
17
+
18
+ - QuadTree2D and KdTree2D (balanced and unbalanced) guarantee the same results for the same input data and the same queries. They are both point-based trees and differ only in construction/query performance characteristics.
19
+ - RTree2D is bounds-based (stores rectangles/AABBs), not points. Its spatial knowledge and query semantics operate on rectangles, so its results will intentionally differ for sized objects and bounds intersection queries.
20
+
21
+ ## Performance Benchmarks
22
+
23
+ <!-- SPATIAL_TREE_BENCHMARKS_START -->
24
+
25
+ ### Datasets
26
+
27
+ <!-- tabs:start -->
28
+
29
+ #### **1,000,000 entries**
30
+
31
+ ##### Construction
32
+
33
+ | Construction | KDTree2D (Balanced) | KDTree2D (Unbalanced) | QuadTree2D | RTree2D |
34
+ | ----------------- | ------------------- | --------------------- | ---------- | ---------- |
35
+ | 1,000,000 entries | 3 (0.325s) | 4 (0.218s) | 4 (0.221s) | 1 (0.595s) |
36
+
37
+ ##### Elements In Range
38
+
39
+ | Elements In Range | KDTree2D (Balanced) | KDTree2D (Unbalanced) | QuadTree2D | RTree2D |
40
+ | --------------------------- | ------------------- | --------------------- | ---------- | ------- |
41
+ | Full (~span/2) (r=499.5) | 58 | 58 | 56 | 7 |
42
+ | Half (~span/4) (r=249.8) | 236 | 238 | 215 | 28 |
43
+ | Quarter (~span/8) (r=124.9) | 945 | 946 | 815 | 119 |
44
+ | Tiny (~span/1000) (r=1) | 103,233 | 105,580 | 142,838 | 107,126 |
45
+
46
+ ##### Get Elements In Bounds
47
+
48
+ | Get Elements In Bounds | KDTree2D (Balanced) | KDTree2D (Unbalanced) | QuadTree2D | RTree2D |
49
+ | -------------------------- | ------------------- | --------------------- | ---------- | ------- |
50
+ | Full (size=999.0x999.0) | 314 | 325 | 344 | 17 |
51
+ | Half (size=499.5x499.5) | 1,730 | 1,822 | 1,238 | 73 |
52
+ | Quarter (size=249.8x249.8) | 7,188 | 7,170 | 3,867 | 379 |
53
+ | Unit (size=1) | 149,753 | 153,363 | 197,026 | 113,010 |
54
+
55
+ ##### Approximate Nearest Neighbors
56
+
57
+ | Approximate Nearest Neighbors | KDTree2D (Balanced) | KDTree2D (Unbalanced) | QuadTree2D | RTree2D |
58
+ | ----------------------------- | ------------------- | --------------------- | ---------- | ------- |
59
+ | 500 neighbors | 8,466 | 16,873 | 12,696 | 70,046 |
60
+ | 100 neighbors | 78,952 | 76,476 | 78,720 | 171,372 |
61
+ | 10 neighbors | 375,484 | 377,708 | 251,988 | 277,491 |
62
+ | 1 neighbor | 551,002 | 508,239 | 276,379 | 299,010 |
63
+
64
+ #### **100,000 entries**
65
+
66
+ ##### Construction
67
+
68
+ | Construction | KDTree2D (Balanced) | KDTree2D (Unbalanced) | QuadTree2D | RTree2D |
69
+ | --------------- | ------------------- | --------------------- | ----------- | ----------- |
70
+ | 100,000 entries | 50 (0.020s) | 83 (0.012s) | 50 (0.020s) | 49 (0.020s) |
71
+
72
+ ##### Elements In Range
73
+
74
+ | Elements In Range | KDTree2D (Balanced) | KDTree2D (Unbalanced) | QuadTree2D | RTree2D |
75
+ | --------------------------- | ------------------- | --------------------- | ---------- | ------- |
76
+ | Full (~span/2) (r=199.5) | 602 | 602 | 600 | 73 |
77
+ | Half (~span/4) (r=99.75) | 1,355 | 1,359 | 1,248 | 185 |
78
+ | Quarter (~span/8) (r=49.88) | 4,672 | 5,178 | 4,300 | 723 |
79
+ | Tiny (~span/1000) (r=1) | 127,810 | 128,060 | 179,544 | 145,029 |
80
+
81
+ ##### Get Elements In Bounds
82
+
83
+ | Get Elements In Bounds | KDTree2D (Balanced) | KDTree2D (Unbalanced) | QuadTree2D | RTree2D |
84
+ | -------------------------- | ------------------- | --------------------- | ---------- | ------- |
85
+ | Full (size=399.0x249.0) | 4,436 | 4,468 | 4,702 | 235 |
86
+ | Half (size=199.5x124.5) | 9,433 | 11,669 | 7,996 | 967 |
87
+ | Quarter (size=99.75x62.25) | 25,419 | 32,186 | 19,754 | 3,805 |
88
+ | Unit (size=1) | 184,712 | 185,636 | 245,390 | 155,220 |
89
+
90
+ ##### Approximate Nearest Neighbors
91
+
92
+ | Approximate Nearest Neighbors | KDTree2D (Balanced) | KDTree2D (Unbalanced) | QuadTree2D | RTree2D |
93
+ | ----------------------------- | ------------------- | --------------------- | ---------- | ------- |
94
+ | 500 neighbors | 9,986 | 9,929 | 11,705 | 69,966 |
95
+ | 100 neighbors | 49,779 | 87,233 | 55,229 | 233,211 |
96
+ | 10 neighbors | 470,175 | 394,286 | 294,299 | 352,517 |
97
+ | 1 neighbor | 509,623 | 544,160 | 314,046 | 350,724 |
98
+
99
+ #### **10,000 entries**
100
+
101
+ ##### Construction
102
+
103
+ | Construction | KDTree2D (Balanced) | KDTree2D (Unbalanced) | QuadTree2D | RTree2D |
104
+ | -------------- | ------------------- | --------------------- | ------------ | ------------ |
105
+ | 10,000 entries | 533 (0.002s) | 796 (0.001s) | 408 (0.002s) | 507 (0.002s) |
106
+
107
+ ##### Elements In Range
108
+
109
+ | Elements In Range | KDTree2D (Balanced) | KDTree2D (Unbalanced) | QuadTree2D | RTree2D |
110
+ | --------------------------- | ------------------- | --------------------- | ---------- | ------- |
111
+ | Full (~span/2) (r=49.50) | 5,944 | 5,941 | 5,936 | 735 |
112
+ | Half (~span/4) (r=24.75) | 22,272 | 22,233 | 13,861 | 2,919 |
113
+ | Quarter (~span/8) (r=12.38) | 44,278 | 51,526 | 38,041 | 12,217 |
114
+ | Tiny (~span/1000) (r=1) | 167,798 | 162,582 | 223,371 | 168,224 |
115
+
116
+ ##### Get Elements In Bounds
117
+
118
+ | Get Elements In Bounds | KDTree2D (Balanced) | KDTree2D (Unbalanced) | QuadTree2D | RTree2D |
119
+ | -------------------------- | ------------------- | --------------------- | ---------- | ------- |
120
+ | Full (size=99.00x99.00) | 45,222 | 44,244 | 47,466 | 2,412 |
121
+ | Half (size=49.50x49.50) | 167,135 | 166,097 | 36,985 | 9,274 |
122
+ | Quarter (size=24.75x24.75) | 76,007 | 104,425 | 74,227 | 35,573 |
123
+ | Unit (size=1) | 242,092 | 234,546 | 320,164 | 181,677 |
124
+
125
+ ##### Approximate Nearest Neighbors
126
+
127
+ | Approximate Nearest Neighbors | KDTree2D (Balanced) | KDTree2D (Unbalanced) | QuadTree2D | RTree2D |
128
+ | ----------------------------- | ------------------- | --------------------- | ---------- | ------- |
129
+ | 500 neighbors | 13,178 | 12,888 | 14,441 | 65,299 |
130
+ | 100 neighbors | 62,415 | 57,120 | 96,738 | 235,553 |
131
+ | 10 neighbors | 418,552 | 392,340 | 316,886 | 420,625 |
132
+ | 1 neighbor | 595,519 | 632,000 | 372,667 | 433,485 |
133
+
134
+ #### **1,000 entries**
135
+
136
+ ##### Construction
137
+
138
+ | Construction | KDTree2D (Balanced) | KDTree2D (Unbalanced) | QuadTree2D | RTree2D |
139
+ | ------------- | ------------------- | --------------------- | -------------- | -------------- |
140
+ | 1,000 entries | 4,672 (0.000s) | 5,611 (0.000s) | 4,847 (0.000s) | 4,764 (0.000s) |
141
+
142
+ ##### Elements In Range
143
+
144
+ | Elements In Range | KDTree2D (Balanced) | KDTree2D (Unbalanced) | QuadTree2D | RTree2D |
145
+ | -------------------------- | ------------------- | --------------------- | ---------- | ------- |
146
+ | Full (~span/2) (r=24.50) | 58,142 | 56,029 | 57,082 | 7,394 |
147
+ | Half (~span/4) (r=12.25) | 60,439 | 76,572 | 57,123 | 14,698 |
148
+ | Quarter (~span/8) (r=6.13) | 95,988 | 108,457 | 95,703 | 37,920 |
149
+ | Tiny (~span/1000) (r=1) | 239,460 | 237,275 | 333,071 | 251,518 |
150
+
151
+ ##### Get Elements In Bounds
152
+
153
+ | Get Elements In Bounds | KDTree2D (Balanced) | KDTree2D (Unbalanced) | QuadTree2D | RTree2D |
154
+ | ------------------------- | ------------------- | --------------------- | ---------- | ------- |
155
+ | Full (size=49.00x19.00) | 499,193 | 498,444 | 508,596 | 24,141 |
156
+ | Half (size=24.50x9.5) | 167,532 | 291,283 | 126,274 | 75,139 |
157
+ | Quarter (size=12.25x4.75) | 271,878 | 288,421 | 194,135 | 176,768 |
158
+ | Unit (size=1) | 342,402 | 339,166 | 460,883 | 281,383 |
159
+
160
+ ##### Approximate Nearest Neighbors
161
+
162
+ | Approximate Nearest Neighbors | KDTree2D (Balanced) | KDTree2D (Unbalanced) | QuadTree2D | RTree2D |
163
+ | ----------------------------- | ------------------- | --------------------- | ---------- | ------- |
164
+ | 500 neighbors | 46,434 | 47,214 | 40,048 | 70,543 |
165
+ | 100 neighbors | 80,837 | 77,933 | 91,884 | 267,760 |
166
+ | 10 neighbors | 487,252 | 574,172 | 426,710 | 516,096 |
167
+ | 1 neighbor | 754,604 | 618,120 | 404,966 | 594,659 |
168
+
169
+ #### **100 entries**
170
+
171
+ ##### Construction
172
+
173
+ | Construction | KDTree2D (Balanced) | KDTree2D (Unbalanced) | QuadTree2D | RTree2D |
174
+ | ------------ | ------------------- | --------------------- | --------------- | --------------- |
175
+ | 100 entries | 37,174 (0.000s) | 3,938 (0.000s) | 10,384 (0.000s) | 21,978 (0.000s) |
176
+
177
+ ##### Elements In Range
178
+
179
+ | Elements In Range | KDTree2D (Balanced) | KDTree2D (Unbalanced) | QuadTree2D | RTree2D |
180
+ | -------------------------- | ------------------- | --------------------- | ---------- | ------- |
181
+ | Full (~span/2) (r=4.5) | 505,197 | 462,582 | 480,895 | 72,679 |
182
+ | Half (~span/4) (r=2.25) | 428,579 | 432,700 | 256,227 | 233,286 |
183
+ | Quarter (~span/8) (r=1.13) | 422,859 | 432,362 | 601,655 | 318,360 |
184
+ | Tiny (~span/1000) (r=1) | 406,482 | 433,055 | 601,161 | 339,515 |
185
+
186
+ ##### Get Elements In Bounds
187
+
188
+ | Get Elements In Bounds | KDTree2D (Balanced) | KDTree2D (Unbalanced) | QuadTree2D | RTree2D |
189
+ | ------------------------ | ------------------- | --------------------- | ---------- | ------- |
190
+ | Full (size=9x9) | 2,460,211 | 2,459,261 | 2,542,373 | 223,694 |
191
+ | Half (size=4.5x4.5) | 572,726 | 561,349 | 365,082 | 372,098 |
192
+ | Quarter (size=2.25x2.25) | 594,157 | 580,857 | 738,232 | 396,288 |
193
+ | Unit (size=1) | 593,669 | 576,995 | 787,477 | 395,564 |
194
+
195
+ ##### Approximate Nearest Neighbors
196
+
197
+ | Approximate Nearest Neighbors | KDTree2D (Balanced) | KDTree2D (Unbalanced) | QuadTree2D | RTree2D |
198
+ | ----------------------------- | ------------------- | --------------------- | ---------- | ------- |
199
+ | 100 neighbors (max) | 166,728 | 165,861 | 199,072 | 303,148 |
200
+ | 10 neighbors | 610,079 | 520,568 | 639,716 | 735,646 |
201
+ | 1 neighbor | 457,409 | 765,967 | 667,953 | 818,651 |
202
+
203
+ <!-- tabs:end -->
204
+ <!-- SPATIAL_TREE_BENCHMARKS_END -->
205
+
206
+ ## Interpreting the Results
207
+
208
+ All numbers represent **operations per second** (higher is better), except for construction times which show operations per second and absolute time.
209
+
210
+ ### Choosing the Right Tree
211
+
212
+ **QuadTree2D**:
213
+
214
+ - Best for: General-purpose 2D spatial queries
215
+ - Strengths: Balanced performance across all operation types, simple to use
216
+ - Weaknesses: Slightly slower than KDTree for point queries
217
+
218
+ **KDTree2D (Balanced)**:
219
+
220
+ - Best for: When you need consistent query performance
221
+ - Strengths: Fast nearest-neighbor queries, good for smaller datasets
222
+ - Weaknesses: Slower construction time
223
+
224
+ **KDTree2D (Unbalanced)**:
225
+
226
+ - Best for: When you need fast construction and will rebuild frequently
227
+ - Strengths: Fastest construction, similar query performance to balanced
228
+ - Weaknesses: May degrade on pathological data distributions
229
+
230
+ **RTree2D**:
231
+
232
+ - Best for: Bounding box queries, especially with large query areas
233
+ - Strengths: Excellent for large bounding box queries, handles overlapping objects well
234
+ - Weaknesses: Slower for point queries and small ranges
235
+
236
+ ### Important Notes
237
+
238
+ - All spatial trees assume **immutable** positional data
239
+ - If positions change, you must reconstruct the tree
240
+ - Spatial queries are O(log n) vs O(n) for linear search
241
+ - Construction cost is amortized over many queries