com.wallstop-studios.unity-helpers 2.0.0-rc81.9 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.editorconfig +1 -1
- package/.gitattributes +1 -1
- package/.githooks/pre-commit +31 -5
- package/.githooks/pre-push +50 -0
- package/.github/dependabot.yml +24 -2
- package/.github/scripts/check-markdown-links.ps1 +77 -0
- package/.github/scripts/check_markdown_links.py +89 -0
- package/.github/scripts/check_markdown_url_encoding.py +74 -0
- package/.github/scripts/validate_markdown_links.py +194 -0
- package/.github/workflows/csharpier-autofix.yml +152 -0
- package/.github/workflows/format-on-demand.yml +305 -0
- package/.github/workflows/lint-doc-links.yml +8 -5
- package/.github/workflows/markdown-json.yml +6 -2
- package/.github/workflows/prettier-autofix.yml +195 -0
- package/.github/workflows/update-dotnet-tools.yml +80 -0
- package/.github/workflows/yaml-format-lint.yml +41 -0
- package/.lychee.toml +4 -4
- package/.markdownlint.jsonc +21 -0
- package/.pre-commit-config.yaml +11 -3
- package/.yamllint.yaml +31 -0
- package/AGENTS.md +5 -1
- package/CHANGELOG.md +11 -0
- package/CONTRIBUTING.md +49 -0
- package/CONTRIBUTING.md.meta +7 -0
- package/EDITOR_TOOLS_GUIDE.md +4 -0
- package/Editor/AnimationEventEditor.cs +337 -160
- package/Editor/Core/Helper/AnimationEventHelpers.cs +178 -152
- package/Editor/CustomEditors/PersistentDirectoryGUI.cs +20 -11
- package/Editor/CustomEditors/TexturePlatformOverrideEntryDrawer.cs +11 -2
- package/Editor/FitTextureSizeWindow.cs +43 -19
- package/Editor/PersistentDirectorySettings.cs +64 -12
- package/Editor/PrefabChecker.cs +72 -5
- package/Editor/Sprites/AnimationCopier.cs +132 -56
- package/Editor/Sprites/AnimationCreator.cs +63 -22
- package/Editor/Sprites/AnimationViewerWindow.cs +42 -6
- package/Editor/Sprites/TexturePlatformNameHelper.cs +50 -39
- package/Editor/Sprites/TextureResizerWizard.cs +23 -1
- package/Editor/Sprites/TextureSettingsApplierWindow.cs +148 -85
- package/Editor/Tools/ImageBlurTool.cs +81 -10
- package/Editor/Utils/EditorUi.cs +1 -1
- package/Editor/Utils/ScriptableObjectSingletonCreator.cs +1 -1
- package/GETTING_STARTED.md +40 -56
- package/RANDOM_PERFORMANCE.md +12 -12
- package/README.md +395 -2407
- package/RELATIONAL_COMPONENTS.md +92 -83
- package/Runtime/AssemblyInfo.cs +2 -0
- package/Runtime/Core/Attributes/NotNullAttribute.cs +1 -3
- package/Runtime/Core/Attributes/RelationalComponentAssigner.cs +50 -5
- package/Runtime/Core/DataStructure/CyclicBuffer.cs +0 -1
- package/Runtime/Core/Extension/RandomExtensions.cs +68 -0
- package/Runtime/Core/Extension/WallstopStudiosLogger.cs +16 -0
- package/Runtime/Core/Helper/Partials/ObjectHelpers.cs +4 -1
- package/Runtime/Core/Helper/ReflectionHelpers.cs +21 -10
- package/Runtime/Core/Helper/SpriteHelpers.cs +3 -1
- package/Runtime/Core/Helper/UnityMainThreadDispatcher.cs +45 -1
- package/Runtime/Core/Serialization/JsonConverters/GameObjectConverter.cs +13 -5
- package/Runtime/Core/Serialization/JsonConverters/ResolutionConverter.cs +1 -1
- package/Runtime/Core/Serialization/JsonConverters/TypeConverter.cs +1 -1
- package/Runtime/Core/Serialization/Serializer.cs +101 -0
- package/Runtime/Integrations/VContainer/AssemblyInfo.cs +9 -0
- package/Runtime/Integrations/VContainer/AssemblyInfo.cs.meta +3 -0
- package/Runtime/Integrations/VContainer/ObjectResolverRelationalExtensions.cs +96 -0
- package/Runtime/Integrations/VContainer/RelationalComponentEntryPoint.cs +90 -10
- package/Runtime/Integrations/VContainer/RelationalComponentsBuilderExtensions.cs +13 -1
- package/Runtime/Integrations/VContainer/RelationalObjectPools.cs +114 -0
- package/Runtime/Integrations/VContainer/RelationalObjectPools.cs.meta +11 -0
- package/Runtime/Integrations/VContainer/RelationalSceneAssignmentOptions.cs +16 -4
- package/Runtime/Integrations/VContainer/RelationalSceneLoadListener.cs +241 -0
- package/Runtime/Integrations/VContainer/RelationalSceneLoadListener.cs.meta +11 -0
- package/Runtime/Integrations/Zenject/AssemblyInfo.cs +9 -0
- package/Runtime/Integrations/Zenject/AssemblyInfo.cs.meta +3 -0
- package/Runtime/Integrations/Zenject/DiContainerRelationalExtensions.cs +69 -2
- package/Runtime/Integrations/Zenject/RelationalComponentSceneInitializer.cs +89 -12
- package/Runtime/Integrations/Zenject/RelationalComponentsInstaller.cs +23 -1
- package/Runtime/Integrations/Zenject/RelationalMemoryPools.cs +44 -0
- package/Runtime/Integrations/Zenject/RelationalMemoryPools.cs.meta +11 -0
- package/Runtime/Integrations/Zenject/RelationalSceneAssignmentOptions.cs +16 -10
- package/Runtime/Integrations/Zenject/RelationalSceneLoadListener.cs +243 -0
- package/Runtime/Integrations/Zenject/RelationalSceneLoadListener.cs.meta +11 -0
- package/Runtime/Tags/AttributeMetadataCache.cs +1 -4
- package/Runtime/Utils/Buffers.cs +4 -4
- package/Runtime/Utils/ScriptableObjectSingleton.cs +0 -1
- package/Runtime/Utils/SetTextureImportData.cs +3 -1
- package/Runtime/Utils/TextureScale.cs +10 -2
- package/Runtime/Visuals/UGUI/EnhancedImage.cs +6 -0
- package/Runtime/Visuals/UIToolkit/LayeredImage.cs +4 -1
- package/SERIALIZATION.md +15 -0
- package/SPATIAL_TREE_2D_PERFORMANCE.md +85 -82
- package/SPATIAL_TREE_3D_PERFORMANCE.md +94 -91
- package/Samples~/DI - VContainer/README.md +232 -51
- package/Samples~/DI - VContainer/Scripts/GameLifetimeScope.cs +22 -4
- package/Samples~/DI - VContainer/Scripts/RelationalConsumer.cs +5 -2
- package/Samples~/DI - VContainer/Scripts/Spawner.cs +113 -4
- package/Samples~/DI - Zenject/README.md +217 -53
- package/Samples~/DI - Zenject/Scripts/RelationalConsumer.cs +3 -0
- package/Samples~/DI - Zenject/Scripts/RelationalConsumerPool.cs +37 -0
- package/Samples~/DI - Zenject/Scripts/RelationalConsumerPool.cs.meta +12 -0
- package/Samples~/DI - Zenject/Scripts/SpawnerZenject.cs +74 -3
- package/Samples~/Random - PRNG/README.md +2 -1
- package/Samples~/Relational Components - Basic/README.md +3 -1
- package/Samples~/Serialization - JSON/README.md +2 -1
- package/Samples~/Spatial Structures - 2D and 3D/README.md +2 -1
- package/Samples~/UGUI - EnhancedImage/README.md +2 -1
- package/Samples~/UI Toolkit - MultiFile Selector (Editor)/README.md +2 -1
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/Tests/Editor/Attributes/AnimationEventHelpersTests.cs +16 -0
- package/Tests/Editor/Core/Attributes/RelationalComponentAssignerTests.cs +3 -3
- package/Tests/Editor/Integrations/VContainer/VContainerRelationalEntryPointTests.cs +6 -2
- package/Tests/Editor/Integrations/VContainer/VContainerRelationalHelpersTests.cs +170 -0
- package/Tests/Editor/Integrations/VContainer/VContainerRelationalHelpersTests.cs.meta +11 -0
- package/Tests/Editor/Integrations/VContainer/WallstopStudios.UnityHelpers.Tests.Editor.VContainer.asmdef +2 -1
- package/Tests/Editor/Integrations/Zenject/WallstopStudios.UnityHelpers.Tests.Editor.Zenject.asmdef +3 -2
- package/Tests/Editor/Integrations/Zenject/ZenjectRelationalHelpersTests.cs +131 -0
- package/Tests/Editor/Integrations/Zenject/ZenjectRelationalHelpersTests.cs.meta +11 -0
- package/Tests/Editor/Integrations/Zenject/ZenjectRelationalInitializerTests.cs +6 -2
- package/Tests/Editor/PersistentDirectorySettingsTests.cs +59 -0
- package/Tests/Editor/PersistentDirectorySettingsTests.cs.meta +11 -0
- package/Tests/Editor/PrefabCheckerReportTests.cs +32 -0
- package/Tests/Editor/PrefabCheckerReportTests.cs.meta +11 -0
- package/Tests/Editor/Sprites/AnimationCopierFilterTests.cs +64 -0
- package/Tests/Editor/Sprites/AnimationCopierFilterTests.cs.meta +11 -0
- package/Tests/Editor/Sprites/AnimationCopierWindowTests.cs +1 -1
- package/Tests/Editor/Sprites/AnimationViewerWindowTests.cs +38 -0
- package/Tests/Editor/Sprites/AnimationViewerWindowTests.cs.meta +11 -0
- package/Tests/Editor/Sprites/ScriptableSpriteAtlasEditorTests.cs +1 -1
- package/Tests/Editor/Sprites/SpriteCropperAdditionalTests.cs +12 -12
- package/Tests/Editor/Sprites/SpriteCropperTests.cs +9 -9
- package/Tests/Editor/Sprites/SpritePivotAdjusterTests.cs +3 -3
- package/Tests/Editor/Sprites/TexturePlatformNameHelperTests.cs +18 -0
- package/Tests/Editor/Sprites/TextureResizerWizardTests.cs +5 -5
- package/Tests/Editor/Sprites/TextureSettingsApplierAPITests.cs +3 -3
- package/Tests/Editor/Sprites/TextureSettingsApplierWizardAdditionalTests.cs +4 -4
- package/Tests/Editor/Sprites/TextureSettingsApplierWizardTests.cs +4 -4
- package/Tests/Editor/Tools/ImageBlurToolTests.cs +22 -110
- package/Tests/Editor/Utils/CommonTestBase.cs +43 -1
- package/Tests/Editor/Utils/ScriptableObjectSingletonCreatorTests.cs +5 -5
- package/Tests/Editor/Windows/FitTextureSizeWindowTests.cs +66 -74
- package/Tests/Runtime/Attributes/RelationalComponentInitializerTests.cs +4 -15
- package/Tests/Runtime/DataStructures/SpatialTree3DBoundsConsistencyTests.cs +29 -29
- package/Tests/Runtime/Integrations/VContainer/RelationalComponentsVContainerTests.cs +259 -218
- package/Tests/Runtime/Integrations/VContainer/RelationalObjectPoolsVContainerTests.cs +86 -0
- package/Tests/Runtime/Integrations/VContainer/RelationalObjectPoolsVContainerTests.cs.meta +11 -0
- package/Tests/Runtime/Integrations/Zenject/RelationalComponentsZenjectTests.cs +255 -227
- package/Tests/Runtime/Performance/SpatialTree2DPerformanceTests.cs +5 -0
- package/Tests/Runtime/Performance/SpatialTree3DPerformanceTests.cs +3 -0
- package/Tests/Runtime/Serialization/JsonConverterAdditionalTests.cs +30 -0
- package/Tests/Runtime/Serialization/JsonConverterAdditionalTests.cs.meta +11 -0
- package/Tests/Runtime/Serialization/JsonConverterTests.cs +8 -12
- package/Tests/Runtime/Serialization/JsonSerializationTest.cs +16 -5
- package/Tests/Runtime/Serialization/SerializerAdditionalTests.cs +12 -0
- package/Tests/Runtime/Serialization/SerializerFileIoTests.cs +105 -0
- package/Tests/Runtime/Serialization/SerializerFileIoTests.cs.meta +11 -0
- package/Tests/Runtime/Serialization/UnityEngineObjectJsonTests.cs +247 -0
- package/Tests/Runtime/Serialization/UnityEngineObjectJsonTests.cs.meta +11 -0
- package/Tests/Runtime/TestUtils/CommonTestBase.cs +88 -0
- package/Tests/Runtime/Utils/CoroutineHandlerTests.cs +1 -1
- package/Tests/Runtime/Utils/LZMAComprehensiveTests.cs +1 -1
- package/Tests/Runtime/Utils/LZMATests.cs +1 -1
- package/Tests/Runtime/Utils/MatchColliderToSpriteTests.cs +1 -1
- package/Tests/Runtime/Visuals/EnhancedImageTests.cs +25 -56
- package/Tests/Runtime/Visuals/VisualsTestHelpers.cs +1 -8
- package/package-lock.json.meta +7 -0
- package/package.json +8 -4
- package/scripts/check-eol.ps1 +4 -5
- package/scripts/lint-tests.ps1 +156 -0
- package/scripts/lint-tests.ps1.meta +7 -0
- package/scripts/normalize-eol.ps1 +6 -9
- package/.github/workflows/csharpier.yml +0 -135
|
@@ -2,17 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
## Why This Integration Matters
|
|
4
4
|
|
|
5
|
-
**
|
|
6
|
-
1. **Dependencies** (injected via constructor/properties/fields)
|
|
7
|
-
2. **Hierarchy references** (SpriteRenderer, Rigidbody2D, child colliders, etc.)
|
|
5
|
+
**Stop Writing GetComponent Boilerplate in Every Single Script**
|
|
8
6
|
|
|
9
|
-
|
|
7
|
+
When using dependency injection with Zenject, you've solved half the problem - your service dependencies get injected cleanly. But you're **still stuck** writing repetitive `GetComponent` boilerplate for hierarchy references in every. single. MonoBehaviour.
|
|
10
8
|
|
|
11
|
-
**The
|
|
9
|
+
**The Painful Reality:**
|
|
10
|
+
|
|
11
|
+
1. **Dependencies** → ✅ Handled by Zenject (IHealthSystem, IAudioService, etc.)
|
|
12
|
+
2. **Hierarchy references** → ❌ Still manual hell (SpriteRenderer, Rigidbody2D, child colliders, etc.)
|
|
13
|
+
|
|
14
|
+
You're using a modern DI framework but still writing 2008-era Unity boilerplate. **Unity Helpers fixes this.**
|
|
15
|
+
|
|
16
|
+
**The Solution:** This integration automatically wires up relational component fields **right after** DI injection completes - giving you the best of both worlds with **literally zero extra code per component**.
|
|
12
17
|
|
|
13
18
|
### ⚡ Quick Example: Before vs After
|
|
14
19
|
|
|
15
20
|
**Before (Manual):**
|
|
21
|
+
|
|
16
22
|
```csharp
|
|
17
23
|
public class Enemy : MonoBehaviour
|
|
18
24
|
{
|
|
@@ -36,6 +42,7 @@ public class Enemy : MonoBehaviour
|
|
|
36
42
|
```
|
|
37
43
|
|
|
38
44
|
**After (With Integration):**
|
|
45
|
+
|
|
39
46
|
```csharp
|
|
40
47
|
public class Enemy : MonoBehaviour
|
|
41
48
|
{
|
|
@@ -50,7 +57,9 @@ public class Enemy : MonoBehaviour
|
|
|
50
57
|
}
|
|
51
58
|
```
|
|
52
59
|
|
|
53
|
-
|
|
60
|
+
**⏱️ Time Saved:** 10-20 lines of boilerplate per component × hundreds of components = **weeks** of development time.
|
|
61
|
+
**🧠 Mental Load Eliminated:** No more context-switching between DI patterns and Unity hierarchy patterns.
|
|
62
|
+
**🐛 Bugs Prevented:** Automatic validation catches missing references **before** they cause runtime errors.
|
|
54
63
|
|
|
55
64
|
---
|
|
56
65
|
|
|
@@ -60,37 +69,47 @@ public class Enemy : MonoBehaviour
|
|
|
60
69
|
|
|
61
70
|
1. Add a `SceneContext` to your scene (if you don't have one already)
|
|
62
71
|
2. Add the `RelationalComponentsInstaller` component to the same GameObject
|
|
63
|
-
3.
|
|
72
|
+
3. Enable **"Assign Scene On Initialize"** to automatically wire all scene components after the container builds (recommended)
|
|
64
73
|
|
|
65
74
|

|
|
66
75
|
|
|
76
|
+
> 💡 **Beginner tip:** Enable both checkboxes in the inspector:
|
|
77
|
+
>
|
|
78
|
+
> - ✅ **Assign Scene On Initialize** → Auto-wires all scene objects (saves you from calling it manually)
|
|
79
|
+
> - ✅ **Listen For Additive Scenes** → Auto-wires newly loaded scenes (great for multi-scene setups)
|
|
80
|
+
|
|
67
81
|
### Step 2: Use With Prefab Instantiation
|
|
68
82
|
|
|
69
|
-
When spawning prefabs at runtime, use
|
|
83
|
+
When spawning prefabs at runtime, use the helpers that combine instantiation, DI, and relational assignment:
|
|
70
84
|
|
|
71
85
|
```csharp
|
|
72
86
|
using UnityEngine;
|
|
73
87
|
using Zenject;
|
|
74
88
|
using WallstopStudios.UnityHelpers.Integrations.Zenject;
|
|
75
89
|
|
|
76
|
-
public class EnemySpawner : MonoBehaviour
|
|
90
|
+
public sealed class EnemySpawner : MonoBehaviour
|
|
77
91
|
{
|
|
78
92
|
[Inject] private DiContainer _container;
|
|
79
93
|
[SerializeField] private Enemy _enemyPrefab;
|
|
94
|
+
[SerializeField] private GameObject _enemySquadPrefab;
|
|
80
95
|
|
|
81
|
-
public
|
|
96
|
+
public Enemy SpawnEnemy(Transform parent)
|
|
82
97
|
{
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
98
|
+
return _container.InstantiateComponentWithRelations(_enemyPrefab, parent);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
public GameObject SpawnEnemySquad(Transform parent)
|
|
102
|
+
{
|
|
103
|
+
return _container.InstantiateGameObjectWithRelations(
|
|
104
|
+
_enemySquadPrefab,
|
|
105
|
+
parent,
|
|
106
|
+
includeInactiveChildren: true
|
|
89
107
|
);
|
|
108
|
+
}
|
|
90
109
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
110
|
+
public void HydrateExisting(GameObject root)
|
|
111
|
+
{
|
|
112
|
+
_container.AssignRelationalHierarchy(root, includeInactiveChildren: true);
|
|
94
113
|
}
|
|
95
114
|
}
|
|
96
115
|
```
|
|
@@ -103,7 +122,8 @@ public class EnemySpawner : MonoBehaviour
|
|
|
103
122
|
|
|
104
123
|
This sample provides a complete working example:
|
|
105
124
|
|
|
106
|
-
- **Scripts/SpawnerZenject.cs** -
|
|
125
|
+
- **Scripts/SpawnerZenject.cs** - Demonstrates `InstantiateComponentWithRelations`, `InstantiateGameObjectWithRelations`, optional pooling, and hierarchy hydration
|
|
126
|
+
- **Scripts/RelationalConsumerPool.cs** - Minimal `RelationalMemoryPool` implementation for use with Zenject memory pools
|
|
107
127
|
- **Scripts/RelationalConsumer.cs** - Component demonstrating relational attributes
|
|
108
128
|
- **Prefabs/RelationalConsumer.prefab** - Example prefab with relational fields
|
|
109
129
|
- **Prefabs/SpawnerZenject.prefab** - Spawner prefab showing runtime usage
|
|
@@ -119,11 +139,15 @@ This sample provides a complete working example:
|
|
|
119
139
|
|
|
120
140
|
---
|
|
121
141
|
|
|
122
|
-
## 🎯 Common Use Cases
|
|
142
|
+
## 🎯 Common Use Cases (By Experience Level)
|
|
143
|
+
|
|
144
|
+
### 🟢 Beginner: "I just want my components to work"
|
|
145
|
+
|
|
146
|
+
**Perfect for:** Player controllers, enemy AI, simple gameplay scripts
|
|
123
147
|
|
|
124
|
-
|
|
148
|
+
**What you get:** No more `GetComponent` calls, no more null reference exceptions from missing components
|
|
125
149
|
|
|
126
|
-
|
|
150
|
+
**Example:**
|
|
127
151
|
|
|
128
152
|
```csharp
|
|
129
153
|
public class PlayerController : MonoBehaviour
|
|
@@ -150,56 +174,56 @@ public class PlayerController : MonoBehaviour
|
|
|
150
174
|
|
|
151
175
|
**Important:** Enable **"Assign Scene On Initialize"** in the `RelationalComponentsInstaller` for automatic scene wiring.
|
|
152
176
|
|
|
153
|
-
###
|
|
177
|
+
### 🟡 Intermediate: "I'm spawning objects at runtime"
|
|
154
178
|
|
|
155
|
-
|
|
179
|
+
**Perfect for:** Enemy spawners, projectile systems, object pooling
|
|
180
|
+
|
|
181
|
+
**What you get:** One-line instantiation that handles DI injection + hierarchy wiring automatically
|
|
182
|
+
|
|
183
|
+
**Example:**
|
|
156
184
|
|
|
157
185
|
```csharp
|
|
158
|
-
public class ProjectileSpawner : MonoBehaviour
|
|
186
|
+
public sealed class ProjectileSpawner : MonoBehaviour
|
|
159
187
|
{
|
|
160
188
|
[Inject] private DiContainer _container;
|
|
161
189
|
[SerializeField] private Projectile _projectilePrefab;
|
|
162
190
|
|
|
163
|
-
public
|
|
191
|
+
public Projectile Fire(Vector3 position, Vector3 direction)
|
|
164
192
|
{
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
_projectilePrefab,
|
|
168
|
-
position,
|
|
169
|
-
Quaternion.LookRotation(direction)
|
|
170
|
-
);
|
|
171
|
-
|
|
193
|
+
Projectile projectile = _container.InstantiateComponentWithRelations(_projectilePrefab);
|
|
194
|
+
projectile.transform.SetPositionAndRotation(position, Quaternion.LookRotation(direction));
|
|
172
195
|
projectile.Launch(direction);
|
|
196
|
+
return projectile;
|
|
173
197
|
}
|
|
174
198
|
}
|
|
175
199
|
```
|
|
176
200
|
|
|
177
|
-
###
|
|
201
|
+
### 🔴 Advanced: "I have complex hierarchies and custom workflows"
|
|
202
|
+
|
|
203
|
+
**Perfect for:** UI systems, vehicles with multiple parts, procedural generation, custom factories
|
|
204
|
+
|
|
205
|
+
**What you get:** Full control over when and how wiring happens, with helpers for every scenario
|
|
178
206
|
|
|
179
|
-
|
|
207
|
+
**Example - Complex Prefabs:**
|
|
180
208
|
|
|
181
209
|
```csharp
|
|
182
|
-
public class VehicleFactory : MonoBehaviour
|
|
210
|
+
public sealed class VehicleFactory : MonoBehaviour
|
|
183
211
|
{
|
|
184
212
|
[Inject] private DiContainer _container;
|
|
185
213
|
[SerializeField] private GameObject _vehiclePrefab;
|
|
186
214
|
|
|
187
215
|
public GameObject CreateVehicle()
|
|
188
216
|
{
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
return vehicle;
|
|
217
|
+
return _container.InstantiateGameObjectWithRelations(
|
|
218
|
+
_vehiclePrefab,
|
|
219
|
+
parent: null,
|
|
220
|
+
includeInactiveChildren: true
|
|
221
|
+
);
|
|
196
222
|
}
|
|
197
223
|
}
|
|
198
224
|
```
|
|
199
225
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
Combine Zenject factories with relational wiring:
|
|
226
|
+
**Example - Custom Factories:**
|
|
203
227
|
|
|
204
228
|
```csharp
|
|
205
229
|
public class EnemyFactory : PlaceholderFactory<Enemy>
|
|
@@ -221,6 +245,81 @@ Container.BindFactory<Enemy, EnemyFactory>()
|
|
|
221
245
|
|
|
222
246
|
---
|
|
223
247
|
|
|
248
|
+
## 💡 Real-World Impact: A Day in the Life
|
|
249
|
+
|
|
250
|
+
### Without This Integration
|
|
251
|
+
|
|
252
|
+
**Morning:** You start work on a new enemy type.
|
|
253
|
+
|
|
254
|
+
```csharp
|
|
255
|
+
public class FlyingEnemy : MonoBehaviour
|
|
256
|
+
{
|
|
257
|
+
[Inject] private IHealthSystem _health;
|
|
258
|
+
[Inject] private IAudioService _audio;
|
|
259
|
+
|
|
260
|
+
private Animator _animator;
|
|
261
|
+
private Rigidbody2D _rigidbody;
|
|
262
|
+
private SpriteRenderer _sprite;
|
|
263
|
+
private Collider2D[] _hitboxes;
|
|
264
|
+
private Transform _weaponMount;
|
|
265
|
+
|
|
266
|
+
void Awake()
|
|
267
|
+
{
|
|
268
|
+
_animator = GetComponent<Animator>();
|
|
269
|
+
if (_animator == null) Debug.LogError("Missing Animator on FlyingEnemy!");
|
|
270
|
+
|
|
271
|
+
_rigidbody = GetComponent<Rigidbody2D>();
|
|
272
|
+
if (_rigidbody == null) Debug.LogError("Missing Rigidbody2D on FlyingEnemy!");
|
|
273
|
+
|
|
274
|
+
_sprite = GetComponent<SpriteRenderer>();
|
|
275
|
+
if (_sprite == null) Debug.LogError("Missing SpriteRenderer on FlyingEnemy!");
|
|
276
|
+
|
|
277
|
+
_hitboxes = GetComponentsInChildren<Collider2D>();
|
|
278
|
+
if (_hitboxes.Length == 0) Debug.LogWarning("No hitboxes found on FlyingEnemy!");
|
|
279
|
+
|
|
280
|
+
_weaponMount = transform.Find("WeaponMount");
|
|
281
|
+
if (_weaponMount == null) Debug.LogError("Missing WeaponMount on FlyingEnemy!");
|
|
282
|
+
|
|
283
|
+
// Finally, actual game logic can start...
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
**10 minutes later:** You've written 20+ lines of boilerplate before writing any actual game logic.
|
|
289
|
+
|
|
290
|
+
**30 minutes later:** Null reference exception in the build! You forgot to add the SpriteRenderer to the prefab.
|
|
291
|
+
|
|
292
|
+
**60 minutes later:** You're manually wiring up the 8th enemy variant of the day...
|
|
293
|
+
|
|
294
|
+
### With This Integration
|
|
295
|
+
|
|
296
|
+
**Morning:** You start work on a new enemy type.
|
|
297
|
+
|
|
298
|
+
```csharp
|
|
299
|
+
public class FlyingEnemy : MonoBehaviour
|
|
300
|
+
{
|
|
301
|
+
[Inject] private IHealthSystem _health;
|
|
302
|
+
[Inject] private IAudioService _audio;
|
|
303
|
+
|
|
304
|
+
[SiblingComponent] private Animator _animator;
|
|
305
|
+
[SiblingComponent] private Rigidbody2D _rigidbody;
|
|
306
|
+
[SiblingComponent] private SpriteRenderer _sprite;
|
|
307
|
+
[ChildComponent] private Collider2D[] _hitboxes;
|
|
308
|
+
[ChildComponent(NameFilter = "WeaponMount")] private Transform _weaponMount;
|
|
309
|
+
|
|
310
|
+
// Start writing game logic immediately
|
|
311
|
+
void Start() => _animator.Play("Idle");
|
|
312
|
+
}
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
**2 minutes later:** You're done with wiring and writing game logic.
|
|
316
|
+
|
|
317
|
+
**10 minutes later:** You've shipped 5 enemy variants with zero boilerplate.
|
|
318
|
+
|
|
319
|
+
**Never:** You never see "Missing component" runtime errors because validation happens automatically with helpful messages.
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
224
323
|
## 🔧 Advanced Configuration
|
|
225
324
|
|
|
226
325
|
### RelationalComponentsInstaller Options
|
|
@@ -228,6 +327,7 @@ Container.BindFactory<Enemy, EnemyFactory>()
|
|
|
228
327
|
The installer component provides these settings:
|
|
229
328
|
|
|
230
329
|
**Assign Scene On Initialize** *(default: true)*
|
|
330
|
+
|
|
231
331
|
- When enabled, automatically wires all scene components with relational attributes after the container builds
|
|
232
332
|
- Disable if you want to manually control when scene wiring happens
|
|
233
333
|
|
|
@@ -276,11 +376,68 @@ Container.BindInterfacesTo<GameBootstrap>().AsSingle();
|
|
|
276
376
|
```
|
|
277
377
|
|
|
278
378
|
Or enable auto-prewarm on the `AttributeMetadataCache` asset:
|
|
379
|
+
|
|
279
380
|
1. Create: `Assets > Create > Wallstop Studios > Unity Helpers > Attribute Metadata Cache`
|
|
280
381
|
2. Enable **"Prewarm Relational On Load"** in the Inspector
|
|
281
382
|
|
|
282
383
|
---
|
|
283
384
|
|
|
385
|
+
## 🧰 Additional Helpers & Recipes
|
|
386
|
+
|
|
387
|
+
### One-liners for DI + Relational Wiring
|
|
388
|
+
|
|
389
|
+
```csharp
|
|
390
|
+
// Inject + assign a single component
|
|
391
|
+
Container.InjectWithRelations(component);
|
|
392
|
+
|
|
393
|
+
// Instantiate a component prefab + assign
|
|
394
|
+
var comp = Container.InstantiateComponentWithRelations(prefabComp, parent);
|
|
395
|
+
|
|
396
|
+
// Inject + assign a whole hierarchy
|
|
397
|
+
Container.InjectGameObjectWithRelations(root, includeInactiveChildren: true);
|
|
398
|
+
|
|
399
|
+
// Instantiate a GameObject prefab + inject + assign hierarchy
|
|
400
|
+
var go = Container.InstantiateGameObjectWithRelations(prefabGo, parent);
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
### Additive Scenes & Options
|
|
404
|
+
|
|
405
|
+
In the `RelationalComponentsInstaller`, enable “Assign Scene On Initialize” and “Listen For Additive Scenes”. You can also control scanning behavior via options:
|
|
406
|
+
|
|
407
|
+
```csharp
|
|
408
|
+
public sealed class GameInstaller : MonoInstaller
|
|
409
|
+
{
|
|
410
|
+
public override void InstallBindings()
|
|
411
|
+
{
|
|
412
|
+
// Bind assigner (done by installer automatically if used)
|
|
413
|
+
// Container.Bind<IRelationalComponentAssigner>().To<RelationalComponentAssigner>().AsSingle();
|
|
414
|
+
|
|
415
|
+
// Configure scan options used by the initializer/listener
|
|
416
|
+
Container.BindInstance(new RelationalSceneAssignmentOptions(
|
|
417
|
+
includeInactive: true,
|
|
418
|
+
useSinglePassScan: true
|
|
419
|
+
));
|
|
420
|
+
|
|
421
|
+
// Register initializer + additive scene listener (installer toggles also available)
|
|
422
|
+
Container.BindInterfacesTo<RelationalComponentSceneInitializer>().AsSingle();
|
|
423
|
+
Container.BindInterfacesTo<RelationalSceneLoadListener>().AsSingle();
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
### Pools
|
|
429
|
+
|
|
430
|
+
Use DI-aware Zenject memory pools to assign on spawn automatically:
|
|
431
|
+
|
|
432
|
+
```csharp
|
|
433
|
+
public class EnemyPool : RelationalMemoryPool<Enemy> {}
|
|
434
|
+
|
|
435
|
+
// Or with a spawn parameter
|
|
436
|
+
public class BulletPool : RelationalMemoryPool<Vector3, Bullet> {}
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
---
|
|
440
|
+
|
|
284
441
|
## ❓ Troubleshooting
|
|
285
442
|
|
|
286
443
|
### My relational fields are null even with the integration
|
|
@@ -293,15 +450,15 @@ Or enable auto-prewarm on the `AttributeMetadataCache` asset:
|
|
|
293
450
|
|
|
294
451
|
2. **Scene components not wired?**
|
|
295
452
|
- Enable **"Assign Scene On Initialize"** in the `RelationalComponentsInstaller`
|
|
296
|
-
- Or manually call `_container.
|
|
453
|
+
- Or manually call `_container.AssignRelationalHierarchy(gameObject, includeInactiveChildren: true)` at bootstrap time
|
|
297
454
|
|
|
298
455
|
3. **Are you using the right attributes?**
|
|
299
456
|
- Fields need `[SiblingComponent]`, `[ParentComponent]`, or `[ChildComponent]` attributes
|
|
300
457
|
- These are different from `[Inject]` - you can use both on the same component
|
|
301
458
|
|
|
302
459
|
4. **Runtime instantiation not working?**
|
|
303
|
-
- Use `_container.InstantiateComponentWithRelations()`
|
|
304
|
-
- Regular `InstantiatePrefab()` won't trigger relational wiring
|
|
460
|
+
- Use `_container.InstantiateComponentWithRelations(...)`, `_container.InstantiateGameObjectWithRelations(...)`, or `_container.AssignRelationalHierarchy(...)`
|
|
461
|
+
- Regular `InstantiatePrefab()`/`InstantiatePrefabForComponent()` won't trigger relational wiring without these helpers
|
|
305
462
|
|
|
306
463
|
5. **Check your filters:**
|
|
307
464
|
- `TagFilter` must match an existing Unity tag exactly
|
|
@@ -310,14 +467,16 @@ Or enable auto-prewarm on the `AttributeMetadataCache` asset:
|
|
|
310
467
|
### Do I need to call AssignRelationalComponents() in Awake()?
|
|
311
468
|
|
|
312
469
|
**No!** The integration handles this automatically:
|
|
470
|
+
|
|
313
471
|
- **Scene objects:** Wired when you enable "Assign Scene On Initialize" (recommended)
|
|
314
|
-
- **Runtime objects:** Wired when you call `InstantiateComponentWithRelations
|
|
472
|
+
- **Runtime objects:** Wired when you call any of the helper methods (`InstantiateComponentWithRelations`, `InstantiateGameObjectWithRelations`, `AssignRelationalHierarchy`, or the pooling helpers built on `RelationalMemoryPool`)
|
|
315
473
|
|
|
316
474
|
Only call `AssignRelationalComponents()` manually if you need fine-grained control.
|
|
317
475
|
|
|
318
476
|
### Does this work without Zenject?
|
|
319
477
|
|
|
320
478
|
**Yes!** The integration gracefully falls back to standard Unity Helpers behavior if Zenject isn't detected. You can:
|
|
479
|
+
|
|
321
480
|
- Adopt incrementally without breaking existing code
|
|
322
481
|
- Use in projects that mix DI and non-DI components
|
|
323
482
|
- Remove Zenject later without refactoring all your components
|
|
@@ -327,6 +486,7 @@ Only call `AssignRelationalComponents()` manually if you need fine-grained contr
|
|
|
327
486
|
**Minimal:** Relational component assignment happens once per component at initialization time. After that, there's zero runtime overhead - the references are just regular fields.
|
|
328
487
|
|
|
329
488
|
**Optimization tips:**
|
|
489
|
+
|
|
330
490
|
- Use `MaxDepth` to limit hierarchy traversal
|
|
331
491
|
- Use `TagFilter` or `NameFilter` to narrow searches
|
|
332
492
|
- Use `OnlyDescendants`/`OnlyAncestors` to exclude self when appropriate
|
|
@@ -334,6 +494,7 @@ Only call `AssignRelationalComponents()` manually if you need fine-grained contr
|
|
|
334
494
|
### Zenject vs Extenject?
|
|
335
495
|
|
|
336
496
|
This integration works with **all** Zenject variants:
|
|
497
|
+
|
|
337
498
|
- **Zenject** (original)
|
|
338
499
|
- **Extenject** (community fork)
|
|
339
500
|
- **Zenject (Modesttree)** (updated original)
|
|
@@ -345,15 +506,18 @@ Unity Helpers automatically detects which one you're using.
|
|
|
345
506
|
## 📚 Learn More
|
|
346
507
|
|
|
347
508
|
**Unity Helpers Documentation:**
|
|
509
|
+
|
|
348
510
|
- [Relational Components Guide](../../RELATIONAL_COMPONENTS.md) - Complete attribute reference and recipes
|
|
349
511
|
- [Getting Started](../../GETTING_STARTED.md) - Unity Helpers quick start guide
|
|
350
512
|
- [Main README](../../README.md) - Full feature overview
|
|
351
513
|
|
|
352
514
|
**Zenject Documentation:**
|
|
515
|
+
|
|
353
516
|
- [Zenject GitHub](https://github.com/modesttree/Zenject) - Official Zenject documentation
|
|
354
517
|
- [Extenject GitHub](https://github.com/svermeulen/Extenject) - Community fork with updates
|
|
355
518
|
|
|
356
519
|
**Troubleshooting:**
|
|
520
|
+
|
|
357
521
|
- [Relational Components Troubleshooting](../../RELATIONAL_COMPONENTS.md#troubleshooting) - Detailed solutions
|
|
358
522
|
- [DI Integration Testing Guide](../../RELATIONAL_COMPONENTS.md#di-integrations-testing-and-edge-cases) - Advanced scenarios
|
|
359
523
|
|
|
@@ -376,7 +540,7 @@ If you're choosing between Zenject and VContainer, here's how the integrations d
|
|
|
376
540
|
|---------|---------|------------|
|
|
377
541
|
| Setup | Add installer to SceneContext | Call in LifetimeScope.Configure() |
|
|
378
542
|
| Scene wiring | Toggle on installer | Automatic |
|
|
379
|
-
| Runtime instantiation | `InstantiateComponentWithRelations()` | `BuildUpWithRelations()` |
|
|
543
|
+
| Runtime instantiation | `InstantiateComponentWithRelations()`, `InstantiateGameObjectWithRelations()`, `RelationalMemoryPool` helpers | `InstantiateComponentWithRelations()`, `InstantiateGameObjectWithRelations()`, `BuildUpWithRelations()`, `RelationalObjectPools` helpers |
|
|
380
544
|
| Performance | Good | Slightly faster |
|
|
381
545
|
| Maintenance | Community-maintained | Actively developed |
|
|
382
546
|
|
|
@@ -384,6 +548,6 @@ Both integrations provide the same relational component features - choose based
|
|
|
384
548
|
|
|
385
549
|
---
|
|
386
550
|
|
|
387
|
-
|
|
551
|
+
## Made with ❤️ by Wallstop Studios
|
|
388
552
|
|
|
389
553
|
*Unity Helpers is production-ready and actively maintained. [Star the repo](https://github.com/wallstop/unity-helpers) if you find it useful!*
|
|
@@ -3,6 +3,9 @@ namespace Samples.UnityHelpers.DI.Zenject
|
|
|
3
3
|
using UnityEngine;
|
|
4
4
|
using WallstopStudios.UnityHelpers.Core.Attributes;
|
|
5
5
|
|
|
6
|
+
/// <summary>
|
|
7
|
+
/// Minimal component that demonstrates relational attributes being resolved by the Zenject integration.
|
|
8
|
+
/// </summary>
|
|
6
9
|
public sealed class RelationalConsumer : MonoBehaviour
|
|
7
10
|
{
|
|
8
11
|
[SiblingComponent]
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
namespace Samples.UnityHelpers.DI.Zenject
|
|
2
|
+
{
|
|
3
|
+
using global::Zenject;
|
|
4
|
+
using UnityEngine;
|
|
5
|
+
using WallstopStudios.UnityHelpers.Integrations.Zenject;
|
|
6
|
+
|
|
7
|
+
/// <summary>
|
|
8
|
+
/// Example Zenject memory pool that automatically hydrates relational fields when items are spawned.
|
|
9
|
+
/// Bind this pool in an installer with
|
|
10
|
+
/// <code>
|
|
11
|
+
/// Container.BindMemoryPool<RelationalConsumer, RelationalConsumerPool>()
|
|
12
|
+
/// .FromComponentInNewPrefab(componentPrefab)
|
|
13
|
+
/// .UnderTransform(poolRoot);
|
|
14
|
+
/// </code>
|
|
15
|
+
/// </summary>
|
|
16
|
+
public sealed class RelationalConsumerPool : RelationalMemoryPool<RelationalConsumer>
|
|
17
|
+
{
|
|
18
|
+
protected override void OnSpawned(RelationalConsumer item)
|
|
19
|
+
{
|
|
20
|
+
base.OnSpawned(item);
|
|
21
|
+
if (item != null)
|
|
22
|
+
{
|
|
23
|
+
item.gameObject.SetActive(true);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
protected override void OnDespawned(RelationalConsumer item)
|
|
28
|
+
{
|
|
29
|
+
if (item != null)
|
|
30
|
+
{
|
|
31
|
+
item.gameObject.SetActive(false);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
base.OnDespawned(item);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -7,14 +7,85 @@ namespace Samples.UnityHelpers.DI.Zenject
|
|
|
7
7
|
public sealed class SpawnerZenject : MonoBehaviour
|
|
8
8
|
{
|
|
9
9
|
[SerializeField]
|
|
10
|
-
private RelationalConsumer
|
|
10
|
+
private RelationalConsumer _componentPrefab;
|
|
11
|
+
|
|
12
|
+
[SerializeField]
|
|
13
|
+
private GameObject _hierarchyPrefab;
|
|
14
|
+
|
|
15
|
+
[SerializeField]
|
|
16
|
+
private Transform _defaultParent;
|
|
11
17
|
|
|
12
18
|
[Inject]
|
|
13
19
|
private DiContainer _container;
|
|
14
20
|
|
|
15
|
-
|
|
21
|
+
[Inject(Optional = true)]
|
|
22
|
+
private RelationalConsumerPool _pool;
|
|
23
|
+
|
|
24
|
+
/// <summary>
|
|
25
|
+
/// Instantiate a component prefab through Zenject so dependencies and relational fields are populated automatically.
|
|
26
|
+
/// </summary>
|
|
27
|
+
public RelationalConsumer SpawnComponent(Transform parent)
|
|
28
|
+
{
|
|
29
|
+
Transform targetParent = parent != null ? parent : _defaultParent;
|
|
30
|
+
return _container.InstantiateComponentWithRelations(_componentPrefab, targetParent);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/// <summary>
|
|
34
|
+
/// Instantiate a hierarchy prefab and hydrate every attributed component beneath it.
|
|
35
|
+
/// </summary>
|
|
36
|
+
public GameObject SpawnHierarchy(Transform parent)
|
|
37
|
+
{
|
|
38
|
+
Transform targetParent = parent != null ? parent : _defaultParent;
|
|
39
|
+
return _container.InstantiateGameObjectWithRelations(
|
|
40
|
+
_hierarchyPrefab,
|
|
41
|
+
targetParent,
|
|
42
|
+
includeInactiveChildren: true
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/// <summary>
|
|
47
|
+
/// Rent an instance from a Zenject memory pool (falls back to SpawnComponent when the pool is not bound).
|
|
48
|
+
/// </summary>
|
|
49
|
+
public RelationalConsumer SpawnFromPool(Transform parent)
|
|
50
|
+
{
|
|
51
|
+
if (_pool == null)
|
|
52
|
+
{
|
|
53
|
+
return SpawnComponent(parent);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
RelationalConsumer instance = _pool.Spawn();
|
|
57
|
+
Transform targetParent = parent != null ? parent : _defaultParent;
|
|
58
|
+
if (targetParent != null)
|
|
59
|
+
{
|
|
60
|
+
instance.transform.SetParent(targetParent, false);
|
|
61
|
+
}
|
|
62
|
+
return instance;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/// <summary>
|
|
66
|
+
/// Return an instance to the pool.
|
|
67
|
+
/// </summary>
|
|
68
|
+
public void DespawnToPool(RelationalConsumer instance)
|
|
16
69
|
{
|
|
17
|
-
|
|
70
|
+
if (_pool == null || instance == null)
|
|
71
|
+
{
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
_pool.Despawn(instance);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/// <summary>
|
|
79
|
+
/// Hydrate an existing hierarchy that was created outside of the container (editor tooling etc.).
|
|
80
|
+
/// </summary>
|
|
81
|
+
public void HydrateExistingHierarchy(GameObject root)
|
|
82
|
+
{
|
|
83
|
+
if (root == null)
|
|
84
|
+
{
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
_container.AssignRelationalHierarchy(root, includeInactiveChildren: true);
|
|
18
89
|
}
|
|
19
90
|
}
|
|
20
91
|
}
|
|
@@ -3,10 +3,11 @@ Random – PRNG Utilities
|
|
|
3
3
|
Shows quick usage of the high-quality PRNGs (e.g., PCG) for integers, floats, Gaussian values, and sampling from collections.
|
|
4
4
|
|
|
5
5
|
How to use
|
|
6
|
+
|
|
6
7
|
- Add `RandomPrngDemo` to any GameObject and press Play.
|
|
7
8
|
- Optionally change the `seed` in the inspector for deterministic sequences.
|
|
8
9
|
|
|
9
10
|
What it shows
|
|
11
|
+
|
|
10
12
|
- `PcgRandom` construction with a seed and sampling `Next`, `NextFloat`, `NextGaussian`.
|
|
11
13
|
- `NextOf` to pick elements from lists.
|
|
12
|
-
|
|
@@ -3,17 +3,19 @@ Relational Components – Basic
|
|
|
3
3
|
This sample demonstrates the built-in Relational Component Attributes without any DI container. Attach the script to a GameObject hierarchy and the fields are auto-assigned at runtime.
|
|
4
4
|
|
|
5
5
|
How to use
|
|
6
|
+
|
|
6
7
|
- Open any scene and create a simple hierarchy with a parent, a child, and a sibling next to the consumer object.
|
|
7
8
|
- Add `RelationalBasicConsumer` to the child object.
|
|
8
9
|
- Enter Play Mode and check the Console for the assigned references.
|
|
9
10
|
|
|
10
11
|
What it shows
|
|
12
|
+
|
|
11
13
|
- `[ParentComponent]` finds components on ancestors (configurable depth).
|
|
12
14
|
- `[SiblingComponent]` finds components on the same GameObject.
|
|
13
15
|
- `[ChildComponent]` finds components on children (recursively).
|
|
14
16
|
- `this.AssignRelationalComponents()` hydrates all relational fields in `Awake()`/`OnEnable()`.
|
|
15
17
|
|
|
16
18
|
Notes
|
|
19
|
+
|
|
17
20
|
- You can adjust filters on attributes: `Optional`, `IncludeInactive`, `TagFilter`, `NameFilter`, and `MaxCount` for collections.
|
|
18
21
|
- For DI integrations, see the separate VContainer/Zenject samples.
|
|
19
|
-
|
|
@@ -3,11 +3,12 @@ Serialization – JSON Converters
|
|
|
3
3
|
Demonstrates serialization of Unity types using System.Text.Json with Unity Helpers’ built-in converters and helper APIs.
|
|
4
4
|
|
|
5
5
|
How to use
|
|
6
|
+
|
|
6
7
|
- Add `JsonSerializationDemo` to any GameObject and press Play.
|
|
7
8
|
- Check the Console for serialized JSON, byte sizes, and a round-trip decode.
|
|
8
9
|
|
|
9
10
|
What it shows
|
|
11
|
+
|
|
10
12
|
- `Serializer.JsonStringify` and `Serializer.JsonDeserialize<T>` for text workflows.
|
|
11
13
|
- `Serializer.JsonSerialize` and `Serializer.JsonDeserialize<T>(byte[])` for UTF-8 bytes.
|
|
12
14
|
- Using `Serializer.CreateFastJsonOptions()` for hot paths.
|
|
13
|
-
|
|
@@ -3,11 +3,12 @@ Spatial Structures – 2D and 3D
|
|
|
3
3
|
Demonstrates building and querying spatial structures for static point sets and grid-based indexing.
|
|
4
4
|
|
|
5
5
|
How to use
|
|
6
|
+
|
|
6
7
|
- Add `SpatialStructuresDemo` to any GameObject and press Play.
|
|
7
8
|
- Adjust `pointCount`, `areaSize`, and `queryRadius` in the inspector.
|
|
8
9
|
|
|
9
10
|
What it shows
|
|
11
|
+
|
|
10
12
|
- `QuadTree2D<T>` created from points with a transformer and radius query.
|
|
11
13
|
- `KdTree2D<T>` approximate nearest neighbors.
|
|
12
14
|
- `SpatialHash2D<T>` bucketed insertion and radius query.
|
|
13
|
-
|