fr.jeanf.scenemanagement 0.3.3 → 0.3.5
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/Runtime/AdditiveLoading/Id.cs +46 -5
- package/Runtime/AdditiveLoading/SceneLoader.cs +0 -76
- package/Runtime/AdditiveLoading/WorldManager.cs +11 -13
- package/Runtime/DynamicLoading/VolumeSystem.cs +105 -113
- package/Samples/Example/RegionData/Region_00/Zones/Zone_01.asset +1 -1
- package/Samples/Example/RegionData/Region_00/Zones/Zone_02.asset +1 -1
- package/Samples/Example/RegionData/Region_00/Zones/Zone_03.asset +1 -1
- package/Samples/Example/RegionData/Region_00/Zones/Zone_04.asset +1 -1
- package/Samples/Example/RegionData/Region_00/Zones/Zone_05.asset +1 -1
- package/Samples/Example/RegionData/Region_00/Zones/Zone_06.asset +1 -1
- package/Samples/Example/RegionData/Region_00/Zones/Zone_07.asset +1 -1
- package/Samples/Example/RegionData/Region_00/Zones/Zone_08.asset +1 -1
- package/Samples/Example/Scenes/Main.unity +4 -4
- package/package.json +1 -1
|
@@ -36,8 +36,6 @@ namespace jeanf.scenemanagement
|
|
|
36
36
|
{
|
|
37
37
|
return id?.id;
|
|
38
38
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
39
|
}
|
|
42
40
|
|
|
43
41
|
#if UNITY_EDITOR
|
|
@@ -64,19 +62,62 @@ namespace jeanf.scenemanagement
|
|
|
64
62
|
// Access the "id" field within the "Id" class
|
|
65
63
|
SerializedProperty idProperty = property.FindPropertyRelative("id");
|
|
66
64
|
|
|
65
|
+
// Show mixed value indicator if multiple objects have different values
|
|
66
|
+
EditorGUI.showMixedValue = idProperty.hasMultipleDifferentValues;
|
|
67
|
+
|
|
67
68
|
// Draw the text field for the "id" string
|
|
68
|
-
|
|
69
|
+
EditorGUI.BeginChangeCheck();
|
|
70
|
+
string newValue = EditorGUI.TextField(fieldRect, idProperty.stringValue);
|
|
71
|
+
if (EditorGUI.EndChangeCheck())
|
|
72
|
+
{
|
|
73
|
+
idProperty.stringValue = newValue;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Reset mixed value display
|
|
77
|
+
EditorGUI.showMixedValue = false;
|
|
69
78
|
|
|
70
79
|
// Draw the "Generate" button
|
|
71
80
|
if (GUI.Button(buttonRect, "Generate"))
|
|
72
81
|
{
|
|
73
|
-
|
|
82
|
+
// Handle multi-object selection properly
|
|
83
|
+
GenerateUniqueIdsForAllTargets(property);
|
|
74
84
|
}
|
|
75
85
|
|
|
76
86
|
// End property drawing
|
|
77
87
|
EditorGUI.EndProperty();
|
|
78
88
|
}
|
|
79
|
-
}
|
|
80
89
|
|
|
90
|
+
private void GenerateUniqueIdsForAllTargets(SerializedProperty property)
|
|
91
|
+
{
|
|
92
|
+
// Get all target objects (handles multi-selection)
|
|
93
|
+
UnityEngine.Object[] targets = property.serializedObject.targetObjects;
|
|
94
|
+
|
|
95
|
+
// Record undo for all targets
|
|
96
|
+
Undo.RecordObjects(targets, "Generate Unique IDs");
|
|
97
|
+
|
|
98
|
+
// Generate unique ID for each target
|
|
99
|
+
foreach (UnityEngine.Object target in targets)
|
|
100
|
+
{
|
|
101
|
+
SerializedObject targetSerializedObject = new SerializedObject(target);
|
|
102
|
+
SerializedProperty targetProperty = targetSerializedObject.FindProperty(property.propertyPath);
|
|
103
|
+
SerializedProperty targetIdProperty = targetProperty.FindPropertyRelative("id");
|
|
104
|
+
|
|
105
|
+
// Generate unique GUID for each object
|
|
106
|
+
targetIdProperty.stringValue = System.Guid.NewGuid().ToString();
|
|
107
|
+
|
|
108
|
+
// Apply changes to this specific target
|
|
109
|
+
targetSerializedObject.ApplyModifiedProperties();
|
|
110
|
+
|
|
111
|
+
// Mark the asset as dirty to ensure it saves
|
|
112
|
+
EditorUtility.SetDirty(target);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Save all modified assets
|
|
116
|
+
AssetDatabase.SaveAssets();
|
|
117
|
+
|
|
118
|
+
// Refresh the inspector to show updated values
|
|
119
|
+
property.serializedObject.Update();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
81
122
|
#endif
|
|
82
123
|
}
|
|
@@ -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(
|
|
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(
|
|
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(
|
|
244
|
+
private void OnRegionChangedFromECS(FixedString128Bytes regionId)
|
|
247
245
|
{
|
|
248
|
-
|
|
249
|
-
if (string.IsNullOrEmpty(
|
|
246
|
+
var id = regionId.ToString();
|
|
247
|
+
if (string.IsNullOrEmpty(id) || _lastNotifiedRegion == regionId) return;
|
|
250
248
|
|
|
251
|
-
if (!_regionDictionary.TryGetValue(
|
|
249
|
+
if (!_regionDictionary.TryGetValue(id, out var region)) return;
|
|
252
250
|
|
|
253
|
-
_lastNotifiedRegion =
|
|
251
|
+
_lastNotifiedRegion = id;
|
|
254
252
|
_currentPlayerRegion = region;
|
|
255
253
|
|
|
256
254
|
OnRegionChange(region);
|
|
@@ -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,
|
|
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
|
-
|
|
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]
|
|
@@ -80,34 +87,27 @@ namespace jeanf.scenemanagement
|
|
|
80
87
|
_toUnloadList.Clear();
|
|
81
88
|
|
|
82
89
|
var relevantPositions = _relevantQuery.ToComponentDataArray<LocalToWorld>(Allocator.TempJob);
|
|
83
|
-
|
|
90
|
+
|
|
91
|
+
if (relevantPositions.Length == 0)
|
|
84
92
|
{
|
|
85
|
-
if (relevantPositions.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
var playerPosition = relevantPositions[0].Position;
|
|
91
|
-
|
|
92
|
-
if (!_precomputedDataInitialized)
|
|
93
|
-
{
|
|
94
|
-
LoadPrecomputedData(ref state);
|
|
95
|
-
_precomputedDataInitialized = true;
|
|
96
|
-
}
|
|
93
|
+
if (relevantPositions.IsCreated) relevantPositions.Dispose();
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
97
96
|
|
|
98
|
-
|
|
97
|
+
var playerPosition = relevantPositions[0].Position;
|
|
99
98
|
|
|
100
|
-
|
|
101
|
-
CheckForZoneAndRegionChange(newPlayerZone);
|
|
102
|
-
ProcessLevelLoadingStates(ref state);
|
|
103
|
-
}
|
|
104
|
-
finally
|
|
99
|
+
if (!_precomputedDataInitialized)
|
|
105
100
|
{
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
relevantPositions.Dispose();
|
|
109
|
-
}
|
|
101
|
+
LoadPrecomputedData(ref state);
|
|
102
|
+
_precomputedDataInitialized = true;
|
|
110
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();
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
[BurstCompile]
|
|
@@ -121,10 +121,10 @@ namespace jeanf.scenemanagement
|
|
|
121
121
|
if (!ShouldCheckVolume(volume.ValueRO.ZoneId))
|
|
122
122
|
continue;
|
|
123
123
|
|
|
124
|
-
var range = volume.ValueRO.Scale
|
|
124
|
+
var range = volume.ValueRO.Scale * 0.5f;
|
|
125
125
|
var pos = transform.ValueRO.Position;
|
|
126
126
|
var distance = math.abs(playerPosition - pos);
|
|
127
|
-
var insideAxis =
|
|
127
|
+
var insideAxis = distance < range;
|
|
128
128
|
|
|
129
129
|
if (insideAxis.x && insideAxis.y && insideAxis.z)
|
|
130
130
|
{
|
|
@@ -144,18 +144,28 @@ namespace jeanf.scenemanagement
|
|
|
144
144
|
private void LoadPrecomputedData(ref SystemState state)
|
|
145
145
|
{
|
|
146
146
|
_zoneToRegionMap.Clear();
|
|
147
|
-
_zoneToCheckableIndex.Clear();
|
|
148
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();
|
|
149
157
|
|
|
150
158
|
var precomputedEntity = _precomputedDataQuery.GetSingletonEntity();
|
|
151
159
|
var precomputedBuffer = SystemAPI.GetBuffer<PrecomputedVolumeDataBuffer>(precomputedEntity);
|
|
152
160
|
|
|
153
|
-
|
|
161
|
+
var tempZoneList = new NativeList<FixedString128Bytes>(100, Allocator.Temp);
|
|
162
|
+
|
|
154
163
|
foreach (var entry in precomputedBuffer)
|
|
155
164
|
{
|
|
156
165
|
if (entry.isZoneRegionMapping && !entry.zoneId.IsEmpty && !entry.regionId.IsEmpty)
|
|
157
166
|
{
|
|
158
167
|
_zoneToRegionMap.TryAdd(entry.zoneId, entry.regionId);
|
|
168
|
+
tempZoneList.Add(entry.zoneId);
|
|
159
169
|
}
|
|
160
170
|
else if (entry.isLandingZone && !entry.landingZoneId.IsEmpty)
|
|
161
171
|
{
|
|
@@ -163,89 +173,86 @@ namespace jeanf.scenemanagement
|
|
|
163
173
|
}
|
|
164
174
|
}
|
|
165
175
|
|
|
166
|
-
|
|
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
|
+
{
|
|
167
185
|
for (int i = 0; i < precomputedBuffer.Length; i++)
|
|
168
186
|
{
|
|
169
187
|
var entry = precomputedBuffer[i];
|
|
170
188
|
if (entry.isHeader && !entry.primaryZoneId.IsEmpty)
|
|
171
189
|
{
|
|
172
|
-
|
|
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);
|
|
173
216
|
}
|
|
174
217
|
}
|
|
175
218
|
}
|
|
176
219
|
|
|
177
220
|
[BurstCompile]
|
|
178
|
-
private void
|
|
221
|
+
private void SetCheckableZones()
|
|
179
222
|
{
|
|
180
223
|
_checkableZoneIds.Clear();
|
|
181
224
|
|
|
182
225
|
if (_currentPlayerZone.IsEmpty)
|
|
183
226
|
{
|
|
184
|
-
|
|
185
|
-
// GC ALLOCATION FIX: Use manual enumeration instead of foreach
|
|
186
|
-
var enumerator = _zoneToRegionMap.GetEnumerator();
|
|
187
|
-
while (enumerator.MoveNext())
|
|
227
|
+
for (int i = 0; i < _allZones.Length; i++)
|
|
188
228
|
{
|
|
189
|
-
_checkableZoneIds.Add(
|
|
229
|
+
_checkableZoneIds.Add(_allZones[i]);
|
|
190
230
|
}
|
|
191
|
-
enumerator.Dispose();
|
|
192
231
|
return;
|
|
193
232
|
}
|
|
194
233
|
|
|
195
|
-
|
|
196
|
-
if (_zoneToCheckableIndex.TryGetValue(_currentPlayerZone, out var headerIndex))
|
|
234
|
+
if (_precomputedCheckableZones.TryGetValue(_currentPlayerZone, out var checkableArray))
|
|
197
235
|
{
|
|
198
|
-
|
|
199
|
-
var precomputedBuffer = SystemAPI.GetBuffer<PrecomputedVolumeDataBuffer>(precomputedEntity);
|
|
200
|
-
|
|
201
|
-
if (headerIndex < precomputedBuffer.Length)
|
|
236
|
+
for (int i = 0; i < checkableArray.Length; i++)
|
|
202
237
|
{
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
for (int i = 0; i < header.count; i++)
|
|
206
|
-
{
|
|
207
|
-
var dataIndex = header.startIndex + i;
|
|
208
|
-
if (dataIndex < precomputedBuffer.Length)
|
|
209
|
-
{
|
|
210
|
-
var dataEntry = precomputedBuffer[dataIndex];
|
|
211
|
-
if (dataEntry.isData && !dataEntry.checkableZoneId.IsEmpty)
|
|
212
|
-
{
|
|
213
|
-
_checkableZoneIds.Add(dataEntry.checkableZoneId);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
238
|
+
_checkableZoneIds.Add(checkableArray[i]);
|
|
217
239
|
}
|
|
218
240
|
}
|
|
219
|
-
|
|
220
|
-
// Always add landing zones
|
|
221
|
-
// GC ALLOCATION FIX: Use manual enumeration instead of foreach
|
|
222
|
-
var landingEnumerator = _landingZones.GetEnumerator();
|
|
223
|
-
while (landingEnumerator.MoveNext())
|
|
224
|
-
{
|
|
225
|
-
_checkableZoneIds.Add(landingEnumerator.Current);
|
|
226
|
-
}
|
|
227
|
-
landingEnumerator.Dispose();
|
|
228
241
|
}
|
|
229
242
|
|
|
230
243
|
[BurstCompile]
|
|
231
244
|
private bool ShouldCheckVolume(FixedString128Bytes zoneId)
|
|
232
245
|
{
|
|
233
246
|
if (zoneId.IsEmpty) return false;
|
|
234
|
-
|
|
235
|
-
if (_currentPlayerZone.IsEmpty)
|
|
236
|
-
{
|
|
237
|
-
return true;
|
|
238
|
-
}
|
|
239
|
-
|
|
247
|
+
if (_currentPlayerZone.IsEmpty) return true;
|
|
240
248
|
return _checkableZoneIds.Contains(zoneId);
|
|
241
249
|
}
|
|
242
250
|
|
|
243
|
-
// GC ALLOCATION FIX: Remove [BurstCompile] and optimize string conversions
|
|
244
251
|
private void CheckForZoneAndRegionChange(FixedString128Bytes newPlayerZone)
|
|
245
252
|
{
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
253
|
+
var zoneChanged = !_currentPlayerZone.Equals(newPlayerZone);
|
|
254
|
+
var regionChanged = false;
|
|
255
|
+
var newPlayerRegion = new FixedString128Bytes();
|
|
249
256
|
|
|
250
257
|
if (!newPlayerZone.IsEmpty && _zoneToRegionMap.TryGetValue(newPlayerZone, out newPlayerRegion))
|
|
251
258
|
{
|
|
@@ -262,31 +269,16 @@ namespace jeanf.scenemanagement
|
|
|
262
269
|
_currentPlayerRegion = newPlayerRegion;
|
|
263
270
|
}
|
|
264
271
|
|
|
265
|
-
// GC ALLOCATION FIX: Only convert to string when absolutely necessary
|
|
266
272
|
if (zoneChanged && !newPlayerZone.IsEmpty && !_lastNotifiedZone.Equals(newPlayerZone))
|
|
267
273
|
{
|
|
268
274
|
_lastNotifiedZone = newPlayerZone;
|
|
269
|
-
|
|
270
|
-
// Only convert if different from last conversion
|
|
271
|
-
if (!_lastZoneStringConverted.Equals(newPlayerZone))
|
|
272
|
-
{
|
|
273
|
-
_lastZoneStringConverted = newPlayerZone;
|
|
274
|
-
var zoneString = newPlayerZone.ToString();
|
|
275
|
-
WorldManager.NotifyZoneChangeFromECS(zoneString);
|
|
276
|
-
}
|
|
275
|
+
WorldManager.NotifyZoneChangeFromECS(newPlayerZone);
|
|
277
276
|
}
|
|
278
277
|
|
|
279
278
|
if (regionChanged && !newPlayerRegion.IsEmpty && !_lastNotifiedRegion.Equals(newPlayerRegion))
|
|
280
279
|
{
|
|
281
280
|
_lastNotifiedRegion = newPlayerRegion;
|
|
282
|
-
|
|
283
|
-
// Only convert if different from last conversion
|
|
284
|
-
if (!_lastRegionStringConverted.Equals(newPlayerRegion))
|
|
285
|
-
{
|
|
286
|
-
_lastRegionStringConverted = newPlayerRegion;
|
|
287
|
-
var regionString = newPlayerRegion.ToString();
|
|
288
|
-
WorldManager.NotifyRegionChangeFromECS(regionString);
|
|
289
|
-
}
|
|
281
|
+
WorldManager.NotifyRegionChangeFromECS(newPlayerRegion);
|
|
290
282
|
}
|
|
291
283
|
}
|
|
292
284
|
|
|
@@ -298,9 +290,9 @@ namespace jeanf.scenemanagement
|
|
|
298
290
|
.WithEntityAccess())
|
|
299
291
|
{
|
|
300
292
|
bool shouldLoad = false;
|
|
301
|
-
|
|
293
|
+
for (int i = 0; i < volumes.Length; i++)
|
|
302
294
|
{
|
|
303
|
-
if (_activeVolumes.Contains(
|
|
295
|
+
if (_activeVolumes.Contains(volumes[i].volumeEntity))
|
|
304
296
|
{
|
|
305
297
|
shouldLoad = true;
|
|
306
298
|
break;
|
|
@@ -317,21 +309,21 @@ namespace jeanf.scenemanagement
|
|
|
317
309
|
}
|
|
318
310
|
}
|
|
319
311
|
|
|
320
|
-
|
|
312
|
+
for (int i = 0; i < _toLoadList.Length; i++)
|
|
321
313
|
{
|
|
322
|
-
var
|
|
323
|
-
streamingData
|
|
324
|
-
|
|
325
|
-
state.EntityManager.SetComponentData(
|
|
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);
|
|
326
318
|
}
|
|
327
319
|
|
|
328
|
-
|
|
320
|
+
for (int i = 0; i < _toUnloadList.Length; i++)
|
|
329
321
|
{
|
|
330
|
-
var
|
|
331
|
-
|
|
332
|
-
|
|
322
|
+
var toUnload = _toUnloadList[i];
|
|
323
|
+
var streamingData = toUnload.Item2;
|
|
324
|
+
SceneSystem.UnloadScene(state.WorldUnmanaged, streamingData.runtimeEntity, SceneSystem.UnloadParameters.DestroyMetaEntities);
|
|
333
325
|
streamingData.runtimeEntity = Entity.Null;
|
|
334
|
-
state.EntityManager.SetComponentData(
|
|
326
|
+
state.EntityManager.SetComponentData(toUnload.Item1, streamingData);
|
|
335
327
|
}
|
|
336
328
|
}
|
|
337
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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.
|
|
3
|
+
"version": "0.3.5",
|
|
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",
|