fr.jeanf.scenemanagement 0.3.2 → 0.3.4

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.
@@ -1,4 +1,3 @@
1
- using System;
2
1
  using System.Collections.Concurrent;
3
2
  using System.Collections.Generic;
4
3
  using System.Threading;
@@ -63,7 +62,6 @@ namespace jeanf.scenemanagement
63
62
  LoadSceneRequest += QueueLoadScene;
64
63
  UnLoadSceneRequest += QueueUnloadScene;
65
64
  UnloadAllScenesRequest += QueueUnloadAllScenes;
66
- FlushScenesRequest += () => IncrementalMemoryFlush().Forget();
67
65
  }
68
66
 
69
67
  private void Unsubscribe()
@@ -105,51 +103,6 @@ namespace jeanf.scenemanagement
105
103
 
106
104
  ProcessUnloadQueue().Forget();
107
105
  }
108
-
109
- private async UniTaskVoid IncrementalMemoryFlush()
110
- {
111
- if (_isFlushingMemory) return;
112
- _isFlushingMemory = true;
113
-
114
- try
115
- {
116
- await UniTask.Delay(TimeSpan.FromSeconds(memoryFlushDelay), DelayType.Realtime);
117
-
118
- var unloadOperation = Resources.UnloadUnusedAssets();
119
- await unloadOperation.ToUniTask();
120
-
121
- if (enableIncrementalGC)
122
- {
123
- await IncrementalGarbageCollection();
124
- }
125
- }
126
- finally
127
- {
128
- _isFlushingMemory = false;
129
- }
130
- }
131
-
132
- private async UniTask IncrementalGarbageCollection()
133
- {
134
- if (GC.MaxGeneration >= 2)
135
- {
136
- for (int generation = 0; generation <= GC.MaxGeneration; generation++)
137
- {
138
- GC.Collect(generation, GCCollectionMode.Optimized, false);
139
-
140
- for (int frame = 0; frame < gcFrameSpread; frame++)
141
- {
142
- await UniTask.Yield();
143
- }
144
- }
145
- }
146
- else
147
- {
148
- GC.Collect(0, GCCollectionMode.Optimized, false);
149
- await UniTask.Yield();
150
- }
151
- }
152
-
153
106
  private async UniTaskVoid ProcessLoadQueue()
154
107
  {
155
108
  if (_isProcessingLoadQueue) return;
@@ -234,11 +187,6 @@ namespace jeanf.scenemanagement
234
187
  }
235
188
  finally
236
189
  {
237
- if (_loadedScenes.Count == 0)
238
- {
239
- IncrementalMemoryFlush().Forget();
240
- }
241
-
242
190
  _isProcessingUnloadQueue = false;
243
191
  if (!_isProcessingLoadQueue && _loadQueue.Count == 0)
244
192
  {
@@ -276,30 +224,6 @@ namespace jeanf.scenemanagement
276
224
  }
277
225
  }
278
226
 
279
- private void OnApplicationFocus(bool hasFocus)
280
- {
281
- if (!hasFocus && enableIncrementalGC)
282
- {
283
- IncrementalMemoryFlush().Forget();
284
- }
285
- }
286
-
287
- private void OnApplicationPause(bool pauseStatus)
288
- {
289
- if (pauseStatus && enableIncrementalGC)
290
- {
291
- IncrementalMemoryFlush().Forget();
292
- }
293
- }
294
-
295
- public void ForceMemoryFlush()
296
- {
297
- if (!_isFlushingMemory)
298
- {
299
- IncrementalMemoryFlush().Forget();
300
- }
301
- }
302
-
303
227
  public bool IsCurrentlyLoading()
304
228
  {
305
229
  return _isProcessingLoadQueue || _isProcessingUnloadQueue || _isFlushingMemory;
@@ -1,8 +1,8 @@
1
1
  using System.Collections.Generic;
2
2
  using UnityEngine;
3
3
  using jeanf.EventSystem;
4
- using jeanf.propertyDrawer;
5
4
  using jeanf.universalplayer;
5
+ using Unity.Collections;
6
6
 
7
7
  namespace jeanf.scenemanagement
8
8
  {
@@ -31,8 +31,8 @@ namespace jeanf.scenemanagement
31
31
  [SerializeField] private StringEventChannelSO regionChangeRequestChannel;
32
32
  [SerializeField] private SendTeleportTarget sendTeleportTarget;
33
33
 
34
- [ReadOnly] [SerializeField] private Zone _currentPlayerZone;
35
- [ReadOnly] [SerializeField] private Region _currentPlayerRegion;
34
+ [propertyDrawer.ReadOnly] [SerializeField] private Zone _currentPlayerZone;
35
+ [propertyDrawer.ReadOnly] [SerializeField] private Region _currentPlayerRegion;
36
36
 
37
37
  private static WorldManager Instance;
38
38
  private static bool _isRegionTransitioning = false;
@@ -212,15 +212,15 @@ namespace jeanf.scenemanagement
212
212
  }
213
213
  }
214
214
 
215
- public static void NotifyZoneChangeFromECS(string zoneId)
215
+ public static void NotifyZoneChangeFromECS(FixedString128Bytes zoneId)
216
216
  {
217
217
  if (Instance != null && !_isRegionTransitioning)
218
218
  {
219
- Instance.OnZoneChangedFromECS(zoneId);
219
+ Instance.OnZoneChangedFromECS(zoneId.ToString());
220
220
  }
221
221
  }
222
222
 
223
- public static void NotifyRegionChangeFromECS(string regionId)
223
+ public static void NotifyRegionChangeFromECS(FixedString128Bytes regionId)
224
224
  {
225
225
  if (Instance != null && !_isRegionTransitioning)
226
226
  {
@@ -230,7 +230,6 @@ namespace jeanf.scenemanagement
230
230
 
231
231
  private void OnZoneChangedFromECS(string zoneId)
232
232
  {
233
- // GC ALLOCATION FIX: Early exit to avoid string operations
234
233
  if (string.IsNullOrEmpty(zoneId) || _lastNotifiedZone == zoneId) return;
235
234
 
236
235
  if (!_zoneDictionary.TryGetValue(zoneId, out var zone)) return;
@@ -238,19 +237,18 @@ namespace jeanf.scenemanagement
238
237
  _lastNotifiedZone = zoneId;
239
238
  _currentPlayerZone = zone;
240
239
 
241
- // GC ALLOCATION FIX: Only invoke if delegates are not null
242
240
  PublishCurrentZoneId?.Invoke(zone.id);
243
241
  PublishAppList(zone);
244
242
  }
245
243
 
246
- private void OnRegionChangedFromECS(string regionId)
244
+ private void OnRegionChangedFromECS(FixedString128Bytes regionId)
247
245
  {
248
- // GC ALLOCATION FIX: Early exit to avoid unnecessary operations
249
- if (string.IsNullOrEmpty(regionId) || _lastNotifiedRegion == regionId) return;
246
+ var id = regionId.ToString();
247
+ if (string.IsNullOrEmpty(id) || _lastNotifiedRegion == regionId) return;
250
248
 
251
- if (!_regionDictionary.TryGetValue(regionId, out var region)) return;
249
+ if (!_regionDictionary.TryGetValue(id, out var region)) return;
252
250
 
253
- _lastNotifiedRegion = regionId;
251
+ _lastNotifiedRegion = id;
254
252
  _currentPlayerRegion = region;
255
253
 
256
254
  OnRegionChange(region);
@@ -107,12 +107,13 @@ namespace jeanf.scenemanagement
107
107
  {
108
108
  if (zone == null) continue;
109
109
 
110
+ // CHANGED: Collect ALL volumes for this zone, not just the first one
110
111
  foreach (var volumeAuth in volumeAuthorings)
111
112
  {
112
113
  if (volumeAuth.zone != null && volumeAuth.zone.id.Equals(zone.id))
113
114
  {
114
115
  regionVolumeMap[region].Add(volumeAuth);
115
- break; // Only add one volume per zone
116
+ // REMOVED: break statement - now collects all volumes for the zone
116
117
  }
117
118
  }
118
119
  }
@@ -125,35 +126,45 @@ namespace jeanf.scenemanagement
125
126
  var volumes = kvp.Value;
126
127
  var color = _regionColors[region];
127
128
 
128
- // Draw volumes (actual size, no labels)
129
- for (int i = 0; i < volumes.Count; i++)
129
+ // Draw all volumes for this region
130
+ foreach (var volume in volumes)
130
131
  {
131
- var currentVolume = volumes[i];
132
- if (currentVolume == null) continue;
132
+ if (volume == null) continue;
133
133
 
134
- var currentPos = currentVolume.transform.position;
135
- var currentScale = currentVolume.transform.localScale;
134
+ var pos = volume.transform.position;
135
+ var scale = volume.transform.localScale;
136
136
 
137
137
  Handles.color = color;
138
- Handles.DrawWireCube(currentPos, currentScale);
138
+ Handles.DrawWireCube(pos, scale);
139
139
  }
140
140
 
141
- // Draw connections between volumes in the same region (red dotted lines)
142
- for (int i = 0; i < volumes.Count; i++)
141
+ // CHANGED: Draw connections between zone centers, not individual volumes
142
+ var zoneVolumeGroups = new Dictionary<string, List<VolumeAuthoring>>();
143
+ foreach (var volume in volumes)
143
144
  {
144
- var currentVolume = volumes[i];
145
- if (currentVolume == null) continue;
145
+ if (volume?.zone == null) continue;
146
146
 
147
- var currentPos = currentVolume.transform.position;
147
+ var zoneId = volume.zone.id.ToString();
148
+ if (!zoneVolumeGroups.ContainsKey(zoneId))
149
+ zoneVolumeGroups[zoneId] = new List<VolumeAuthoring>();
148
150
 
149
- for (int j = i + 1; j < volumes.Count; j++)
151
+ zoneVolumeGroups[zoneId].Add(volume);
152
+ }
153
+
154
+ // Draw connections between zone centers (red dotted lines)
155
+ var zoneIds = zoneVolumeGroups.Keys.ToList();
156
+ for (int i = 0; i < zoneIds.Count; i++)
157
+ {
158
+ for (int j = i + 1; j < zoneIds.Count; j++)
150
159
  {
151
- var otherVolume = volumes[j];
152
- if (otherVolume == null) continue;
160
+ var zoneA = zoneVolumeGroups[zoneIds[i]];
161
+ var zoneB = zoneVolumeGroups[zoneIds[j]];
162
+
163
+ var centerA = CalculateZoneCenter(zoneA);
164
+ var centerB = CalculateZoneCenter(zoneB);
153
165
 
154
- var otherPos = otherVolume.transform.position;
155
166
  Handles.color = Color.red;
156
- Handles.DrawDottedLine(currentPos, otherPos, 5f);
167
+ Handles.DrawDottedLine(centerA, centerB, 5f);
157
168
  }
158
169
  }
159
170
  }
@@ -163,14 +174,15 @@ namespace jeanf.scenemanagement
163
174
  {
164
175
  if (landing.landingZone == null || landing.region == null) continue;
165
176
 
166
- var landingVolume = System.Array.Find(volumeAuthorings,
167
- v => v.zone != null && v.zone.id.Equals(landing.landingZone.id));
177
+ // CHANGED: Find ALL volumes for the landing zone
178
+ var landingVolumes = System.Array.FindAll(volumeAuthorings,
179
+ v => v.zone != null && v.zone.id.Equals(landing.landingZone.id)).ToList();
168
180
 
169
- if (landingVolume == null) continue;
181
+ if (landingVolumes.Count == 0) continue;
170
182
 
171
- var landingPos = landingVolume.transform.position;
183
+ var landingCenter = CalculateZoneCenter(landingVolumes);
172
184
 
173
- // Connect landing zone to volumes in OTHER regions only
185
+ // Connect landing zone center to volumes in OTHER regions only
174
186
  foreach (var kvp in regionVolumeMap)
175
187
  {
176
188
  var region = kvp.Key;
@@ -178,13 +190,16 @@ namespace jeanf.scenemanagement
178
190
 
179
191
  if (region.id.Equals(landing.region.id)) continue; // Skip same region
180
192
 
181
- foreach (var regionVolume in volumes)
193
+ // Group volumes by zone and connect to zone centers
194
+ var zoneGroups = volumes.GroupBy(v => v.zone?.id.ToString()).Where(g => !string.IsNullOrEmpty(g.Key));
195
+
196
+ foreach (var zoneGroup in zoneGroups)
182
197
  {
183
- if (regionVolume != null)
184
- {
185
- Handles.color = Color.yellow;
186
- Handles.DrawLine(landingPos, regionVolume.transform.position);
187
- }
198
+ var zoneVolumes = zoneGroup.ToList();
199
+ var zoneCenter = CalculateZoneCenter(zoneVolumes);
200
+
201
+ Handles.color = Color.yellow;
202
+ Handles.DrawLine(landingCenter, zoneCenter);
188
203
  }
189
204
  }
190
205
  }
@@ -194,18 +209,36 @@ namespace jeanf.scenemanagement
194
209
  {
195
210
  if (landing.landingZone == null || landing.region == null) continue;
196
211
 
197
- var landingVolume = System.Array.Find(volumeAuthorings,
198
- v => v.zone != null && v.zone.id.Equals(landing.landingZone.id));
212
+ // CHANGED: Find ALL volumes for the landing zone
213
+ var landingVolumes = System.Array.FindAll(volumeAuthorings,
214
+ v => v.zone != null && v.zone.id.Equals(landing.landingZone.id)).ToList();
199
215
 
200
- if (landingVolume == null) continue;
216
+ if (landingVolumes.Count == 0) continue;
201
217
 
202
- var landingPos = landingVolume.transform.position;
203
- var landingScale = landingVolume.transform.localScale;
204
-
205
- // Draw landing zone in blue, actual size
206
- Handles.color = Color.blue;
207
- Handles.DrawWireCube(landingPos, landingScale);
218
+ // Draw all landing zone volumes in blue, actual size
219
+ foreach (var landingVolume in landingVolumes)
220
+ {
221
+ var landingPos = landingVolume.transform.position;
222
+ var landingScale = landingVolume.transform.localScale;
223
+
224
+ Handles.color = Color.blue;
225
+ Handles.DrawWireCube(landingPos, landingScale);
226
+ }
227
+ }
228
+ }
229
+
230
+ // Helper method to calculate the center point of a multi-volume zone
231
+ private Vector3 CalculateZoneCenter(List<VolumeAuthoring> volumes)
232
+ {
233
+ if (volumes.Count == 0) return Vector3.zero;
234
+ if (volumes.Count == 1) return volumes[0].transform.position;
235
+
236
+ Vector3 sum = Vector3.zero;
237
+ foreach (var volume in volumes)
238
+ {
239
+ sum += volume.transform.position;
208
240
  }
241
+ return sum / volumes.Count;
209
242
  }
210
243
 
211
244
  private void DrawLandingZoneConnections(RegionConnectivity connectivity, VolumeAuthoring[] volumeAuthorings, Dictionary<Region, List<VolumeAuthoring>> regionVolumeMap)
@@ -214,18 +247,26 @@ namespace jeanf.scenemanagement
214
247
  {
215
248
  if (landing.landingZone == null || landing.region == null) continue;
216
249
 
217
- var landingVolume = System.Array.Find(volumeAuthorings,
218
- v => v.zone != null && v.zone.id.Equals(landing.landingZone.id));
250
+ // CHANGED: Find ALL volumes for the landing zone
251
+ var landingVolumes = System.Array.FindAll(volumeAuthorings,
252
+ v => v.zone != null && v.zone.id.Equals(landing.landingZone.id)).ToList();
253
+
254
+ if (landingVolumes.Count == 0) continue;
219
255
 
220
- if (landingVolume == null) continue;
256
+ var landingCenter = CalculateZoneCenter(landingVolumes);
221
257
 
222
- var landingPos = landingVolume.transform.position;
223
- var landingScale = landingVolume.transform.localScale;
258
+ // Draw all landing zone volumes
259
+ foreach (var landingVolume in landingVolumes)
260
+ {
261
+ var landingPos = landingVolume.transform.position;
262
+ var landingScale = landingVolume.transform.localScale;
263
+
264
+ Handles.color = Color.white;
265
+ Handles.DrawWireCube(landingPos, landingScale * 1.2f);
266
+ }
224
267
 
225
- Handles.color = Color.white;
226
- Handles.DrawWireCube(landingPos, landingScale * 1.2f);
227
- Handles.Label(landingPos + Vector3.up * (landingScale.y * 0.8f),
228
- $"LANDING\n{landing.landingZone.zoneName}",
268
+ Handles.Label(landingCenter + Vector3.up * 2f,
269
+ $"LANDING\n{landing.landingZone.zoneName}\n({landingVolumes.Count} volumes)",
229
270
  new GUIStyle(GUI.skin.label) {
230
271
  normal = { textColor = Color.white },
231
272
  fontStyle = FontStyle.Bold
@@ -238,13 +279,16 @@ namespace jeanf.scenemanagement
238
279
 
239
280
  if (region.id.Equals(landing.region.id)) continue;
240
281
 
241
- foreach (var regionVolume in volumes)
282
+ // Group volumes by zone and connect to zone centers
283
+ var zoneGroups = volumes.GroupBy(v => v.zone?.id.ToString()).Where(g => !string.IsNullOrEmpty(g.Key));
284
+
285
+ foreach (var zoneGroup in zoneGroups)
242
286
  {
243
- if (regionVolume != null)
244
- {
245
- Handles.color = Color.yellow;
246
- Handles.DrawLine(landingPos, regionVolume.transform.position);
247
- }
287
+ var zoneVolumes = zoneGroup.ToList();
288
+ var zoneCenter = CalculateZoneCenter(zoneVolumes);
289
+
290
+ Handles.color = Color.yellow;
291
+ Handles.DrawLine(landingCenter, zoneCenter);
248
292
  }
249
293
  }
250
294
  }
@@ -344,11 +388,13 @@ namespace jeanf.scenemanagement
344
388
  {
345
389
  if (zone == null) continue;
346
390
 
391
+ // CHANGED: Collect ALL volumes for this zone
347
392
  foreach (var volumeAuth in volumeAuthorings)
348
393
  {
349
394
  if (volumeAuth.zone != null && volumeAuth.zone.id.Equals(zone.id))
350
395
  {
351
396
  regionVolumeMap[region].Add(volumeAuth);
397
+ // REMOVED: break statement
352
398
  }
353
399
  }
354
400
  }
@@ -362,26 +408,51 @@ namespace jeanf.scenemanagement
362
408
 
363
409
  Handles.color = color;
364
410
 
365
- for (int i = 0; i < volumes.Count; i++)
411
+ // Draw all volumes in this region
412
+ foreach (var volume in volumes)
366
413
  {
367
- var currentVolume = volumes[i];
368
- if (currentVolume == null) continue;
414
+ if (volume == null) continue;
369
415
 
370
- var currentPos = currentVolume.transform.position;
371
- var currentScale = currentVolume.transform.localScale;
416
+ var currentPos = volume.transform.position;
417
+ var currentScale = volume.transform.localScale;
372
418
 
373
419
  Handles.DrawWireCube(currentPos, currentScale);
374
- Handles.Label(currentPos + Vector3.up * (currentScale.y * 0.6f),
375
- $"{region.levelName}\n{currentVolume.zone.zoneName}",
376
- new GUIStyle(GUI.skin.label) { normal = { textColor = color } });
377
420
 
378
- for (int j = i + 1; j < volumes.Count; j++)
421
+ // Only show label for first volume of each zone to avoid clutter
422
+ var isFirstVolumeOfZone = volumes.Where(v => v?.zone?.id == volume.zone?.id).First() == volume;
423
+ if (isFirstVolumeOfZone)
379
424
  {
380
- var otherVolume = volumes[j];
381
- if (otherVolume == null) continue;
425
+ Handles.Label(currentPos + Vector3.up * (currentScale.y * 0.6f),
426
+ $"{region.levelName}\n{volume.zone.zoneName}",
427
+ new GUIStyle(GUI.skin.label) { normal = { textColor = color } });
428
+ }
429
+ }
430
+
431
+ // CHANGED: Draw connections between zone centers
432
+ var zoneVolumeGroups = new Dictionary<string, List<VolumeAuthoring>>();
433
+ foreach (var volume in volumes)
434
+ {
435
+ if (volume?.zone == null) continue;
436
+
437
+ var zoneId = volume.zone.id.ToString();
438
+ if (!zoneVolumeGroups.ContainsKey(zoneId))
439
+ zoneVolumeGroups[zoneId] = new List<VolumeAuthoring>();
440
+
441
+ zoneVolumeGroups[zoneId].Add(volume);
442
+ }
443
+
444
+ var zoneIds = zoneVolumeGroups.Keys.ToList();
445
+ for (int i = 0; i < zoneIds.Count; i++)
446
+ {
447
+ for (int j = i + 1; j < zoneIds.Count; j++)
448
+ {
449
+ var zoneA = zoneVolumeGroups[zoneIds[i]];
450
+ var zoneB = zoneVolumeGroups[zoneIds[j]];
451
+
452
+ var centerA = CalculateZoneCenter(zoneA);
453
+ var centerB = CalculateZoneCenter(zoneB);
382
454
 
383
- var otherPos = otherVolume.transform.position;
384
- Handles.DrawDottedLine(currentPos, otherPos, 5f);
455
+ Handles.DrawDottedLine(centerA, centerB, 5f);
385
456
  }
386
457
  }
387
458
  }
@@ -389,24 +460,45 @@ namespace jeanf.scenemanagement
389
460
  DrawLandingZoneConnections(connectivity, volumeAuthorings, regionVolumeMap);
390
461
  }
391
462
 
463
+ private Vector3 CalculateZoneCenter(List<VolumeAuthoring> volumes)
464
+ {
465
+ if (volumes.Count == 0) return Vector3.zero;
466
+ if (volumes.Count == 1) return volumes[0].transform.position;
467
+
468
+ Vector3 sum = Vector3.zero;
469
+ foreach (var volume in volumes)
470
+ {
471
+ sum += volume.transform.position;
472
+ }
473
+ return sum / volumes.Count;
474
+ }
475
+
392
476
  private void DrawLandingZoneConnections(RegionConnectivity connectivity, VolumeAuthoring[] volumeAuthorings, Dictionary<Region, List<VolumeAuthoring>> regionVolumeMap)
393
477
  {
394
478
  foreach (var landing in connectivity.landingZones)
395
479
  {
396
480
  if (landing.landingZone == null || landing.region == null) continue;
397
481
 
398
- var landingVolume = System.Array.Find(volumeAuthorings,
399
- v => v.zone != null && v.zone.id.Equals(landing.landingZone.id));
482
+ // CHANGED: Find ALL volumes for the landing zone
483
+ var landingVolumes = System.Array.FindAll(volumeAuthorings,
484
+ v => v.zone != null && v.zone.id.Equals(landing.landingZone.id)).ToList();
485
+
486
+ if (landingVolumes.Count == 0) continue;
400
487
 
401
- if (landingVolume == null) continue;
488
+ var landingCenter = CalculateZoneCenter(landingVolumes);
402
489
 
403
- var landingPos = landingVolume.transform.position;
404
- var landingScale = landingVolume.transform.localScale;
490
+ // Draw all landing zone volumes
491
+ foreach (var landingVolume in landingVolumes)
492
+ {
493
+ var landingPos = landingVolume.transform.position;
494
+ var landingScale = landingVolume.transform.localScale;
495
+
496
+ Handles.color = Color.white;
497
+ Handles.DrawWireCube(landingPos, landingScale * 1.2f);
498
+ }
405
499
 
406
- Handles.color = Color.white;
407
- Handles.DrawWireCube(landingPos, landingScale * 1.2f);
408
- Handles.Label(landingPos + Vector3.up * (landingScale.y * 0.8f),
409
- $"LANDING\n{landing.landingZone.zoneName}",
500
+ Handles.Label(landingCenter + Vector3.up * 2f,
501
+ $"LANDING\n{landing.landingZone.zoneName}\n({landingVolumes.Count} volumes)",
410
502
  new GUIStyle(GUI.skin.label) {
411
503
  normal = { textColor = Color.white },
412
504
  fontStyle = FontStyle.Bold
@@ -419,13 +511,16 @@ namespace jeanf.scenemanagement
419
511
 
420
512
  if (region.id.Equals(landing.region.id)) continue;
421
513
 
422
- foreach (var regionVolume in volumes)
514
+ // Group by zone and connect to zone centers
515
+ var zoneGroups = volumes.GroupBy(v => v.zone?.id.ToString()).Where(g => !string.IsNullOrEmpty(g.Key));
516
+
517
+ foreach (var zoneGroup in zoneGroups)
423
518
  {
424
- if (regionVolume != null)
425
- {
426
- Handles.color = Color.yellow;
427
- Handles.DrawLine(landingPos, regionVolume.transform.position);
428
- }
519
+ var zoneVolumes = zoneGroup.ToList();
520
+ var zoneCenter = CalculateZoneCenter(zoneVolumes);
521
+
522
+ Handles.color = Color.yellow;
523
+ Handles.DrawLine(landingCenter, zoneCenter);
429
524
  }
430
525
  }
431
526
  }
@@ -623,99 +718,100 @@ namespace jeanf.scenemanagement
623
718
  }
624
719
 
625
720
  var regionColor = _regionColors[currentRegion];
626
- var selectedPos = selectedVolume.transform.position;
627
- var selectedScale = selectedVolume.transform.localScale;
721
+
722
+ // CHANGED: Calculate center of the selected zone (which may have multiple volumes)
723
+ var selectedZoneVolumes = System.Array.FindAll(allVolumeAuthorings,
724
+ v => v.zone != null && v.zone.id.Equals(currentZone.id)).ToList();
725
+ var selectedZoneCenter = CalculateZoneCenter(selectedZoneVolumes);
628
726
 
629
727
  // Priority 3: Draw other connections first (same region) - red dotted lines
630
728
  foreach (var zone in currentRegion.zonesInThisRegion)
631
729
  {
632
730
  if (zone == null || zone == currentZone) continue;
633
731
 
634
- foreach (var volumeAuth in allVolumeAuthorings)
732
+ // CHANGED: Find ALL volumes for this zone and draw connections to zone center
733
+ var zoneVolumes = System.Array.FindAll(allVolumeAuthorings,
734
+ v => v.zone != null && v.zone.id.Equals(zone.id)).ToList();
735
+
736
+ if (zoneVolumes.Count == 0) continue;
737
+
738
+ var zoneCenter = CalculateZoneCenter(zoneVolumes);
739
+
740
+ // Draw all volumes in this zone
741
+ foreach (var volume in zoneVolumes)
635
742
  {
636
- if (volumeAuth == null || volumeAuth.zone == null) continue;
637
-
638
- if (volumeAuth.zone.id.Equals(zone.id))
639
- {
640
- var otherPos = volumeAuth.transform.position;
641
- var otherScale = volumeAuth.transform.localScale;
642
-
643
- // Draw the volume
644
- Handles.color = regionColor;
645
- Handles.DrawWireCube(otherPos, otherScale);
646
-
647
- // Draw potential connection (red dotted line)
648
- Handles.color = Color.red;
649
- Handles.DrawDottedLine(selectedPos, otherPos, 5f);
650
- break; // Only draw one volume per zone
651
- }
743
+ Handles.color = regionColor;
744
+ Handles.DrawWireCube(volume.transform.position, volume.transform.localScale);
652
745
  }
746
+
747
+ // Draw connection line between zone centers
748
+ Handles.color = Color.red;
749
+ Handles.DrawDottedLine(selectedZoneCenter, zoneCenter, 5f);
653
750
  }
654
751
 
655
- // Show actual landing zone connectivity - yellow solid lines
752
+ // Handle landing zone connections
656
753
  var landingConnection = _foundConnectivity.landingZones.FirstOrDefault(l => l.landingZone == currentZone);
657
754
  if (landingConnection != null)
658
755
  {
659
- // This volume IS a landing zone - show connections to OTHER regions
756
+ // This zone IS a landing zone - show connections to OTHER regions
660
757
  foreach (var region in _foundConnectivity.activeRegions)
661
758
  {
662
- if (region == null || region.id.Equals(currentRegion.id)) continue; // Skip same region
663
-
664
- if (!_regionColors.ContainsKey(region))
665
- {
666
- var colorIndex = _regionColors.Count % _predefinedColors.Length;
667
- _regionColors[region] = _predefinedColors[colorIndex];
668
- }
759
+ if (region == null || region.id.Equals(currentRegion.id)) continue;
669
760
 
670
761
  foreach (var zone in region.zonesInThisRegion)
671
762
  {
672
763
  if (zone == null) continue;
673
764
 
674
- foreach (var volumeAuth in allVolumeAuthorings)
765
+ var zoneVolumes = System.Array.FindAll(allVolumeAuthorings,
766
+ v => v.zone != null && v.zone.id.Equals(zone.id)).ToList();
767
+
768
+ if (zoneVolumes.Count == 0) continue;
769
+
770
+ var zoneCenter = CalculateZoneCenter(zoneVolumes);
771
+
772
+ // Draw zone volumes
773
+ foreach (var volume in zoneVolumes)
675
774
  {
676
- if (volumeAuth == null || volumeAuth.zone == null) continue;
677
-
678
- if (volumeAuth.zone.id.Equals(zone.id))
775
+ if (!_regionColors.ContainsKey(region))
679
776
  {
680
- var otherPos = volumeAuth.transform.position;
681
- var otherScale = volumeAuth.transform.localScale;
682
-
683
- // Draw the target volume
684
- Handles.color = _regionColors[region];
685
- Handles.DrawWireCube(otherPos, otherScale);
686
-
687
- // Draw ACTUAL landing zone connection (yellow solid line)
688
- Handles.color = Color.yellow;
689
- Handles.DrawLine(selectedPos, otherPos);
690
- break; // Only draw one volume per zone
777
+ var colorIndex = _regionColors.Count % _predefinedColors.Length;
778
+ _regionColors[region] = _predefinedColors[colorIndex];
691
779
  }
780
+
781
+ Handles.color = _regionColors[region];
782
+ Handles.DrawWireCube(volume.transform.position, volume.transform.localScale);
692
783
  }
784
+
785
+ // Draw landing connection
786
+ Handles.color = Color.yellow;
787
+ Handles.DrawLine(selectedZoneCenter, zoneCenter);
693
788
  }
694
789
  }
695
790
  }
696
791
 
697
- // Show connections FROM other landing zones TO this volume
792
+ // Draw connections FROM other landing zones TO this zone
698
793
  foreach (var landing in _foundConnectivity.landingZones)
699
794
  {
700
795
  if (landing.landingZone == null || landing.region == null) continue;
701
- if (landing.landingZone == currentZone) continue; // Skip self
796
+ if (landing.landingZone == currentZone) continue;
797
+
798
+ var landingVolumes = System.Array.FindAll(allVolumeAuthorings,
799
+ v => v.zone != null && v.zone.id.Equals(landing.landingZone.id)).ToList();
800
+
801
+ if (landingVolumes.Count == 0) continue;
702
802
 
703
- // Find the landing zone volume
704
- foreach (var volumeAuth in allVolumeAuthorings)
803
+ var landingCenter = CalculateZoneCenter(landingVolumes);
804
+
805
+ // Draw landing zone volumes in blue
806
+ foreach (var volume in landingVolumes)
705
807
  {
706
- if (volumeAuth == null || volumeAuth.zone == null) continue;
707
-
708
- if (volumeAuth.zone.id.Equals(landing.landingZone.id))
709
- {
710
- var landingPos = volumeAuth.transform.position;
711
- var landingScale = volumeAuth.transform.localScale;
712
-
713
- // Draw ACTUAL connection from landing zone to current volume (yellow solid line)
714
- Handles.color = Color.yellow;
715
- Handles.DrawLine(landingPos, selectedPos);
716
- break;
717
- }
808
+ Handles.color = Color.blue;
809
+ Handles.DrawWireCube(volume.transform.position, volume.transform.localScale);
718
810
  }
811
+
812
+ // Draw connection
813
+ Handles.color = Color.yellow;
814
+ Handles.DrawLine(landingCenter, selectedZoneCenter);
719
815
  }
720
816
 
721
817
  // Priority 2: Draw landing zones - blue boxes, same size as volume
@@ -724,34 +820,51 @@ namespace jeanf.scenemanagement
724
820
  if (landing.landingZone == null || landing.region == null) continue;
725
821
  if (landing.landingZone == currentZone) continue; // Skip self (will be drawn as selected)
726
822
 
727
- // Find the landing zone volume
728
- foreach (var volumeAuth in allVolumeAuthorings)
823
+ // Find all landing zone volumes
824
+ var landingVolumes = System.Array.FindAll(allVolumeAuthorings,
825
+ v => v.zone != null && v.zone.id.Equals(landing.landingZone.id)).ToList();
826
+
827
+ if (landingVolumes.Count == 0) continue;
828
+
829
+ // Draw landing zone volumes in blue, same size as volume
830
+ foreach (var landingVolume in landingVolumes)
729
831
  {
730
- if (volumeAuth == null || volumeAuth.zone == null) continue;
832
+ var landingPos = landingVolume.transform.position;
833
+ var landingScale = landingVolume.transform.localScale;
731
834
 
732
- if (volumeAuth.zone.id.Equals(landing.landingZone.id))
733
- {
734
- var landingPos = volumeAuth.transform.position;
735
- var landingScale = volumeAuth.transform.localScale;
736
-
737
- // Draw landing zone in blue, same size as volume
738
- Handles.color = Color.blue;
739
- Handles.DrawWireCube(landingPos, landingScale);
740
- break;
741
- }
835
+ Handles.color = Color.blue;
836
+ Handles.DrawWireCube(landingPos, landingScale);
742
837
  }
743
838
  }
744
839
 
745
- // Priority 1: Draw selected volume last - yellow box, actual size
746
- Handles.color = Color.yellow;
747
- Handles.DrawWireCube(selectedPos, selectedScale);
748
- Handles.Label(selectedPos + Vector3.up * (selectedScale.y * 0.7f),
749
- $"SELECTED\n{currentZone.zoneName}",
840
+ // Priority 1: Draw selected zone volumes last - yellow boxes, actual size
841
+ foreach (var selectedVol in selectedZoneVolumes)
842
+ {
843
+ Handles.color = Color.yellow;
844
+ Handles.DrawWireCube(selectedVol.transform.position, selectedVol.transform.localScale);
845
+ }
846
+
847
+ // Add label for the selected zone at the zone center
848
+ Handles.Label(selectedZoneCenter + Vector3.up * 2f,
849
+ $"SELECTED ZONE\n{currentZone.zoneName}\n({selectedZoneVolumes.Count} volumes)",
750
850
  new GUIStyle(GUI.skin.label) {
751
851
  normal = { textColor = Color.yellow },
752
852
  fontStyle = FontStyle.Bold
753
853
  });
754
854
  }
855
+
856
+ private Vector3 CalculateZoneCenter(List<VolumeAuthoring> volumes)
857
+ {
858
+ if (volumes.Count == 0) return Vector3.zero;
859
+ if (volumes.Count == 1) return volumes[0].transform.position;
860
+
861
+ Vector3 sum = Vector3.zero;
862
+ foreach (var volume in volumes)
863
+ {
864
+ sum += volume.transform.position;
865
+ }
866
+ return sum / volumes.Count;
867
+ }
755
868
  }
756
869
 
757
870
  [CustomPropertyDrawer(typeof(LandingZoneData))]
@@ -25,13 +25,10 @@ namespace jeanf.scenemanagement
25
25
  private FixedString128Bytes _lastNotifiedRegion;
26
26
 
27
27
  private NativeHashMap<FixedString128Bytes, FixedString128Bytes> _zoneToRegionMap;
28
- private NativeHashMap<FixedString128Bytes, int> _zoneToCheckableIndex;
28
+ private NativeHashMap<FixedString128Bytes, NativeArray<FixedString128Bytes>> _precomputedCheckableZones;
29
29
  private NativeHashSet<FixedString128Bytes> _landingZones;
30
+ private NativeArray<FixedString128Bytes> _allZones;
30
31
  private bool _precomputedDataInitialized;
31
-
32
- // GC ALLOCATION FIX: Cache string conversions
33
- private FixedString128Bytes _lastZoneStringConverted;
34
- private FixedString128Bytes _lastRegionStringConverted;
35
32
 
36
33
  [BurstCompile]
37
34
  public void OnCreate(ref SystemState state)
@@ -44,15 +41,13 @@ namespace jeanf.scenemanagement
44
41
  _toUnloadList = new NativeList<(Entity, LevelInfo)>(10, Allocator.Persistent);
45
42
  _checkableZoneIds = new NativeHashSet<FixedString128Bytes>(50, Allocator.Persistent);
46
43
  _zoneToRegionMap = new NativeHashMap<FixedString128Bytes, FixedString128Bytes>(100, Allocator.Persistent);
47
- _zoneToCheckableIndex = new NativeHashMap<FixedString128Bytes, int>(100, Allocator.Persistent);
44
+ _precomputedCheckableZones = new NativeHashMap<FixedString128Bytes, NativeArray<FixedString128Bytes>>(100, Allocator.Persistent);
48
45
  _landingZones = new NativeHashSet<FixedString128Bytes>(50, Allocator.Persistent);
49
46
 
50
47
  _currentPlayerZone = new FixedString128Bytes();
51
48
  _currentPlayerRegion = new FixedString128Bytes();
52
49
  _lastNotifiedZone = new FixedString128Bytes();
53
50
  _lastNotifiedRegion = new FixedString128Bytes();
54
- _lastZoneStringConverted = new FixedString128Bytes();
55
- _lastRegionStringConverted = new FixedString128Bytes();
56
51
  _precomputedDataInitialized = false;
57
52
 
58
53
  _relevantQuery = SystemAPI.QueryBuilder().WithAll<Relevant, LocalToWorld>().Build();
@@ -68,8 +63,20 @@ namespace jeanf.scenemanagement
68
63
  if (_toUnloadList.IsCreated) _toUnloadList.Dispose();
69
64
  if (_checkableZoneIds.IsCreated) _checkableZoneIds.Dispose();
70
65
  if (_zoneToRegionMap.IsCreated) _zoneToRegionMap.Dispose();
71
- if (_zoneToCheckableIndex.IsCreated) _zoneToCheckableIndex.Dispose();
72
66
  if (_landingZones.IsCreated) _landingZones.Dispose();
67
+ if (_allZones.IsCreated) _allZones.Dispose();
68
+
69
+ if (_precomputedCheckableZones.IsCreated)
70
+ {
71
+ var enumerator = _precomputedCheckableZones.GetEnumerator();
72
+ while (enumerator.MoveNext())
73
+ {
74
+ if (enumerator.Current.Value.IsCreated)
75
+ enumerator.Current.Value.Dispose();
76
+ }
77
+ enumerator.Dispose();
78
+ _precomputedCheckableZones.Dispose();
79
+ }
73
80
  }
74
81
 
75
82
  [BurstCompile]
@@ -79,36 +86,28 @@ namespace jeanf.scenemanagement
79
86
  _toLoadList.Clear();
80
87
  _toUnloadList.Clear();
81
88
 
82
- // GC ALLOCATION FIX: Use try-finally for guaranteed disposal
83
89
  var relevantPositions = _relevantQuery.ToComponentDataArray<LocalToWorld>(Allocator.TempJob);
84
- try
90
+
91
+ if (relevantPositions.Length == 0)
85
92
  {
86
- if (relevantPositions.Length == 0)
87
- {
88
- return;
89
- }
90
-
91
- var playerPosition = relevantPositions[0].Position;
92
-
93
- if (!_precomputedDataInitialized)
94
- {
95
- LoadPrecomputedData(ref state);
96
- _precomputedDataInitialized = true;
97
- }
93
+ if (relevantPositions.IsCreated) relevantPositions.Dispose();
94
+ return;
95
+ }
98
96
 
99
- UpdateCheckableZonesFromPrecomputed(ref state);
97
+ var playerPosition = relevantPositions[0].Position;
100
98
 
101
- var newPlayerZone = CheckVolumesForPlayerZone(ref state, playerPosition);
102
- CheckForZoneAndRegionChange(newPlayerZone);
103
- ProcessLevelLoadingStates(ref state);
104
- }
105
- finally
99
+ if (!_precomputedDataInitialized)
106
100
  {
107
- if (relevantPositions.IsCreated)
108
- {
109
- relevantPositions.Dispose();
110
- }
101
+ LoadPrecomputedData(ref state);
102
+ _precomputedDataInitialized = true;
111
103
  }
104
+
105
+ SetCheckableZones();
106
+ var newPlayerZone = CheckVolumesForPlayerZone(ref state, playerPosition);
107
+ CheckForZoneAndRegionChange(newPlayerZone);
108
+ ProcessLevelLoadingStates(ref state);
109
+
110
+ if (relevantPositions.IsCreated) relevantPositions.Dispose();
112
111
  }
113
112
 
114
113
  [BurstCompile]
@@ -122,10 +121,10 @@ namespace jeanf.scenemanagement
122
121
  if (!ShouldCheckVolume(volume.ValueRO.ZoneId))
123
122
  continue;
124
123
 
125
- var range = volume.ValueRO.Scale / 2f;
124
+ var range = volume.ValueRO.Scale * 0.5f;
126
125
  var pos = transform.ValueRO.Position;
127
126
  var distance = math.abs(playerPosition - pos);
128
- var insideAxis = (distance < range);
127
+ var insideAxis = distance < range;
129
128
 
130
129
  if (insideAxis.x && insideAxis.y && insideAxis.z)
131
130
  {
@@ -145,18 +144,28 @@ namespace jeanf.scenemanagement
145
144
  private void LoadPrecomputedData(ref SystemState state)
146
145
  {
147
146
  _zoneToRegionMap.Clear();
148
- _zoneToCheckableIndex.Clear();
149
147
  _landingZones.Clear();
148
+
149
+ var enumerator = _precomputedCheckableZones.GetEnumerator();
150
+ while (enumerator.MoveNext())
151
+ {
152
+ if (enumerator.Current.Value.IsCreated)
153
+ enumerator.Current.Value.Dispose();
154
+ }
155
+ enumerator.Dispose();
156
+ _precomputedCheckableZones.Clear();
150
157
 
151
158
  var precomputedEntity = _precomputedDataQuery.GetSingletonEntity();
152
159
  var precomputedBuffer = SystemAPI.GetBuffer<PrecomputedVolumeDataBuffer>(precomputedEntity);
153
160
 
154
- // Load zone-region mappings and landing zones
161
+ var tempZoneList = new NativeList<FixedString128Bytes>(100, Allocator.Temp);
162
+
155
163
  foreach (var entry in precomputedBuffer)
156
164
  {
157
165
  if (entry.isZoneRegionMapping && !entry.zoneId.IsEmpty && !entry.regionId.IsEmpty)
158
166
  {
159
167
  _zoneToRegionMap.TryAdd(entry.zoneId, entry.regionId);
168
+ tempZoneList.Add(entry.zoneId);
160
169
  }
161
170
  else if (entry.isLandingZone && !entry.landingZoneId.IsEmpty)
162
171
  {
@@ -164,89 +173,86 @@ namespace jeanf.scenemanagement
164
173
  }
165
174
  }
166
175
 
167
- // Build checkable zone index
176
+ _allZones = tempZoneList.ToArray(Allocator.Persistent);
177
+ tempZoneList.Dispose();
178
+
179
+ BuildPrecomputedCheckableZones(ref state, precomputedBuffer);
180
+ }
181
+
182
+ [BurstCompile]
183
+ private void BuildPrecomputedCheckableZones(ref SystemState state, DynamicBuffer<PrecomputedVolumeDataBuffer> precomputedBuffer)
184
+ {
168
185
  for (int i = 0; i < precomputedBuffer.Length; i++)
169
186
  {
170
187
  var entry = precomputedBuffer[i];
171
188
  if (entry.isHeader && !entry.primaryZoneId.IsEmpty)
172
189
  {
173
- _zoneToCheckableIndex.TryAdd(entry.primaryZoneId, i);
190
+ var tempList = new NativeList<FixedString128Bytes>(entry.count + _landingZones.Count, Allocator.Temp);
191
+
192
+ for (int j = 0; j < entry.count; j++)
193
+ {
194
+ var dataIndex = entry.startIndex + j;
195
+ if (dataIndex < precomputedBuffer.Length)
196
+ {
197
+ var dataEntry = precomputedBuffer[dataIndex];
198
+ if (dataEntry.isData && !dataEntry.checkableZoneId.IsEmpty)
199
+ {
200
+ tempList.Add(dataEntry.checkableZoneId);
201
+ }
202
+ }
203
+ }
204
+
205
+ var landingEnumerator = _landingZones.GetEnumerator();
206
+ while (landingEnumerator.MoveNext())
207
+ {
208
+ tempList.Add(landingEnumerator.Current);
209
+ }
210
+ landingEnumerator.Dispose();
211
+
212
+ var checkableArray = tempList.ToArray(Allocator.Persistent);
213
+ tempList.Dispose();
214
+
215
+ _precomputedCheckableZones.TryAdd(entry.primaryZoneId, checkableArray);
174
216
  }
175
217
  }
176
218
  }
177
219
 
178
220
  [BurstCompile]
179
- private void UpdateCheckableZonesFromPrecomputed(ref SystemState state)
221
+ private void SetCheckableZones()
180
222
  {
181
223
  _checkableZoneIds.Clear();
182
224
 
183
225
  if (_currentPlayerZone.IsEmpty)
184
226
  {
185
- // Bootstrap state - add all zones
186
- // GC ALLOCATION FIX: Use manual enumeration instead of foreach
187
- var enumerator = _zoneToRegionMap.GetEnumerator();
188
- while (enumerator.MoveNext())
227
+ for (int i = 0; i < _allZones.Length; i++)
189
228
  {
190
- _checkableZoneIds.Add(enumerator.Current.Key);
229
+ _checkableZoneIds.Add(_allZones[i]);
191
230
  }
192
- enumerator.Dispose();
193
231
  return;
194
232
  }
195
233
 
196
- // Find precomputed checkable zones for current zone
197
- if (_zoneToCheckableIndex.TryGetValue(_currentPlayerZone, out var headerIndex))
234
+ if (_precomputedCheckableZones.TryGetValue(_currentPlayerZone, out var checkableArray))
198
235
  {
199
- var precomputedEntity = _precomputedDataQuery.GetSingletonEntity();
200
- var precomputedBuffer = SystemAPI.GetBuffer<PrecomputedVolumeDataBuffer>(precomputedEntity);
201
-
202
- if (headerIndex < precomputedBuffer.Length)
236
+ for (int i = 0; i < checkableArray.Length; i++)
203
237
  {
204
- var header = precomputedBuffer[headerIndex];
205
-
206
- for (int i = 0; i < header.count; i++)
207
- {
208
- var dataIndex = header.startIndex + i;
209
- if (dataIndex < precomputedBuffer.Length)
210
- {
211
- var dataEntry = precomputedBuffer[dataIndex];
212
- if (dataEntry.isData && !dataEntry.checkableZoneId.IsEmpty)
213
- {
214
- _checkableZoneIds.Add(dataEntry.checkableZoneId);
215
- }
216
- }
217
- }
238
+ _checkableZoneIds.Add(checkableArray[i]);
218
239
  }
219
240
  }
220
-
221
- // Always add landing zones
222
- // GC ALLOCATION FIX: Use manual enumeration instead of foreach
223
- var landingEnumerator = _landingZones.GetEnumerator();
224
- while (landingEnumerator.MoveNext())
225
- {
226
- _checkableZoneIds.Add(landingEnumerator.Current);
227
- }
228
- landingEnumerator.Dispose();
229
241
  }
230
242
 
231
243
  [BurstCompile]
232
244
  private bool ShouldCheckVolume(FixedString128Bytes zoneId)
233
245
  {
234
246
  if (zoneId.IsEmpty) return false;
235
-
236
- if (_currentPlayerZone.IsEmpty)
237
- {
238
- return true;
239
- }
240
-
247
+ if (_currentPlayerZone.IsEmpty) return true;
241
248
  return _checkableZoneIds.Contains(zoneId);
242
249
  }
243
250
 
244
- // GC ALLOCATION FIX: Remove [BurstCompile] and optimize string conversions
245
251
  private void CheckForZoneAndRegionChange(FixedString128Bytes newPlayerZone)
246
252
  {
247
- bool zoneChanged = !_currentPlayerZone.Equals(newPlayerZone);
248
- bool regionChanged = false;
249
- FixedString128Bytes newPlayerRegion = new FixedString128Bytes();
253
+ var zoneChanged = !_currentPlayerZone.Equals(newPlayerZone);
254
+ var regionChanged = false;
255
+ var newPlayerRegion = new FixedString128Bytes();
250
256
 
251
257
  if (!newPlayerZone.IsEmpty && _zoneToRegionMap.TryGetValue(newPlayerZone, out newPlayerRegion))
252
258
  {
@@ -263,31 +269,16 @@ namespace jeanf.scenemanagement
263
269
  _currentPlayerRegion = newPlayerRegion;
264
270
  }
265
271
 
266
- // GC ALLOCATION FIX: Only convert to string when absolutely necessary
267
272
  if (zoneChanged && !newPlayerZone.IsEmpty && !_lastNotifiedZone.Equals(newPlayerZone))
268
273
  {
269
274
  _lastNotifiedZone = newPlayerZone;
270
-
271
- // Only convert if different from last conversion
272
- if (!_lastZoneStringConverted.Equals(newPlayerZone))
273
- {
274
- _lastZoneStringConverted = newPlayerZone;
275
- var zoneString = newPlayerZone.ToString();
276
- WorldManager.NotifyZoneChangeFromECS(zoneString);
277
- }
275
+ WorldManager.NotifyZoneChangeFromECS(newPlayerZone);
278
276
  }
279
277
 
280
278
  if (regionChanged && !newPlayerRegion.IsEmpty && !_lastNotifiedRegion.Equals(newPlayerRegion))
281
279
  {
282
280
  _lastNotifiedRegion = newPlayerRegion;
283
-
284
- // Only convert if different from last conversion
285
- if (!_lastRegionStringConverted.Equals(newPlayerRegion))
286
- {
287
- _lastRegionStringConverted = newPlayerRegion;
288
- var regionString = newPlayerRegion.ToString();
289
- WorldManager.NotifyRegionChangeFromECS(regionString);
290
- }
281
+ WorldManager.NotifyRegionChangeFromECS(newPlayerRegion);
291
282
  }
292
283
  }
293
284
 
@@ -299,9 +290,9 @@ namespace jeanf.scenemanagement
299
290
  .WithEntityAccess())
300
291
  {
301
292
  bool shouldLoad = false;
302
- foreach (var volume in volumes)
293
+ for (int i = 0; i < volumes.Length; i++)
303
294
  {
304
- if (_activeVolumes.Contains(volume.volumeEntity))
295
+ if (_activeVolumes.Contains(volumes[i].volumeEntity))
305
296
  {
306
297
  shouldLoad = true;
307
298
  break;
@@ -318,21 +309,21 @@ namespace jeanf.scenemanagement
318
309
  }
319
310
  }
320
311
 
321
- foreach (var toLoad in _toLoadList)
312
+ for (int i = 0; i < _toLoadList.Length; i++)
322
313
  {
323
- var (entity, streamingData) = toLoad;
324
- streamingData.runtimeEntity =
325
- SceneSystem.LoadSceneAsync(state.WorldUnmanaged, streamingData.sceneReference);
326
- state.EntityManager.SetComponentData(entity, streamingData);
314
+ var toLoad = _toLoadList[i];
315
+ var streamingData = toLoad.Item2;
316
+ streamingData.runtimeEntity = SceneSystem.LoadSceneAsync(state.WorldUnmanaged, streamingData.sceneReference);
317
+ state.EntityManager.SetComponentData(toLoad.Item1, streamingData);
327
318
  }
328
319
 
329
- foreach (var toUnload in _toUnloadList)
320
+ for (int i = 0; i < _toUnloadList.Length; i++)
330
321
  {
331
- var (entity, streamingData) = toUnload;
332
- SceneSystem.UnloadScene(state.WorldUnmanaged, streamingData.runtimeEntity,
333
- SceneSystem.UnloadParameters.DestroyMetaEntities);
322
+ var toUnload = _toUnloadList[i];
323
+ var streamingData = toUnload.Item2;
324
+ SceneSystem.UnloadScene(state.WorldUnmanaged, streamingData.runtimeEntity, SceneSystem.UnloadParameters.DestroyMetaEntities);
334
325
  streamingData.runtimeEntity = Entity.Null;
335
- state.EntityManager.SetComponentData(entity, streamingData);
326
+ state.EntityManager.SetComponentData(toUnload.Item1, streamingData);
336
327
  }
337
328
  }
338
329
  }
@@ -547,17 +547,17 @@ PrefabInstance:
547
547
  - target: {fileID: 7951339239912631404, guid: e87a4cab69290cb40805f373b8ccd8d7,
548
548
  type: 3}
549
549
  propertyPath: m_LocalPosition.x
550
- value: -16.722126
550
+ value: 0
551
551
  objectReference: {fileID: 0}
552
552
  - target: {fileID: 7951339239912631404, guid: e87a4cab69290cb40805f373b8ccd8d7,
553
553
  type: 3}
554
554
  propertyPath: m_LocalPosition.y
555
- value: 1.5052338
555
+ value: 0
556
556
  objectReference: {fileID: 0}
557
557
  - target: {fileID: 7951339239912631404, guid: e87a4cab69290cb40805f373b8ccd8d7,
558
558
  type: 3}
559
559
  propertyPath: m_LocalPosition.z
560
- value: 2.0478456
560
+ value: 0
561
561
  objectReference: {fileID: 0}
562
562
  - target: {fileID: 7951339239912631404, guid: e87a4cab69290cb40805f373b8ccd8d7,
563
563
  type: 3}
@@ -2114,7 +2114,7 @@ PrefabInstance:
2114
2114
  - target: {fileID: 2423214379621556911, guid: 15d66d68a4116d243b7bb3b273842708,
2115
2115
  type: 3}
2116
2116
  propertyPath: m_LocalPosition.y
2117
- value: 0
2117
+ value: 1.98
2118
2118
  objectReference: {fileID: 0}
2119
2119
  - target: {fileID: 2423214379621556911, guid: 15d66d68a4116d243b7bb3b273842708,
2120
2120
  type: 3}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fr.jeanf.scenemanagement",
3
- "version": "0.3.2",
3
+ "version": "0.3.4",
4
4
  "displayName": "Scene Management",
5
5
  "description": "This package contains two scene loading system, one is additive, the other is to load subscenes. \nBoth system are living side-by-side.\nThe dynamic systems handles the loading of all static content (environment) using subscenes.\nThe additive system loads scene additively depending on zone & region and upon scenario load/unload requests. Each region or scenario can have dependency that will remain loaded until either a region or a scenario became irrelevant.",
6
6
  "unity": "2021.3",