fr.jeanf.scenemanagement 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Runtime/AdditiveLoading/Editor/WorldManagerEditor.cs +83 -0
- package/Runtime/AdditiveLoading/Editor/WorldManagerEditor.cs.meta +2 -0
- package/Runtime/AdditiveLoading/SceneLoader.cs +89 -15
- package/Runtime/AdditiveLoading/WorldManager.cs +217 -75
- package/Runtime/DynamicLoading/FollowSystem.cs +24 -13
- package/Runtime/DynamicLoading/RegionConnectivity.cs +36 -0
- package/Runtime/DynamicLoading/VolumeSystem.cs +156 -63
- package/Samples/Example/RegionData/Region_00/Region_00.asset +1 -1
- package/Samples/Example/RegionData/Region_01/Region_01.asset +3 -3
- package/Samples/Example/RegionData/Region_02/Region_02.asset +3 -3
- package/Samples/Example/RegionData/Region_02/Zones/Zone_22.asset +1 -1
- package/Samples/Example/RegionData/Region_02/Zones/Zone_23.asset +1 -1
- package/Samples/Example/RegionData/Region_02/Zones/Zone_24.asset +1 -1
- package/Samples/Example/RegionData/Region_02/Zones/Zone_25.asset +1 -1
- package/Samples/Example/RegionData/Region_02/Zones/Zone_26.asset +1 -1
- package/Samples/Example/RegionData/Region_02/Zones/Zone_27.asset +1 -1
- package/Samples/Example/RegionData/Region_02/Zones/Zone_28.asset +1 -1
- package/Samples/Example/Scenes/Main.unity +5 -5
- package/Samples/Setup/AdditiveLoading.prefab +7 -1
- package/package.json +1 -1
- /package/Samples/Example/Scenes/01/{1.unity → 11.unity} +0 -0
- /package/Samples/Example/Scenes/01/{1.unity.meta → 11.unity.meta} +0 -0
- /package/Samples/Example/Scenes/01/{2.unity → 12.unity} +0 -0
- /package/Samples/Example/Scenes/01/{2.unity.meta → 12.unity.meta} +0 -0
- /package/Samples/Example/Scenes/01/{3.unity → 13.unity} +0 -0
- /package/Samples/Example/Scenes/01/{3.unity.meta → 13.unity.meta} +0 -0
- /package/Samples/Example/Scenes/01/{4.unity → 14.unity} +0 -0
- /package/Samples/Example/Scenes/01/{4.unity.meta → 14.unity.meta} +0 -0
- /package/Samples/Example/Scenes/01/{5.unity → 15.unity} +0 -0
- /package/Samples/Example/Scenes/01/{5.unity.meta → 15.unity.meta} +0 -0
- /package/Samples/Example/Scenes/01/{6.unity → 16.unity} +0 -0
- /package/Samples/Example/Scenes/01/{6.unity.meta → 16.unity.meta} +0 -0
- /package/Samples/Example/Scenes/01/{7.unity → 17.unity} +0 -0
- /package/Samples/Example/Scenes/01/{7.unity.meta → 17.unity.meta} +0 -0
- /package/Samples/Example/Scenes/01/{8.unity → 18.unity} +0 -0
- /package/Samples/Example/Scenes/01/{8.unity.meta → 18.unity.meta} +0 -0
- /package/Samples/Example/Scenes/02/{1.unity → 21.unity} +0 -0
- /package/Samples/Example/Scenes/02/{1.unity.meta → 21.unity.meta} +0 -0
- /package/Samples/Example/Scenes/02/{2.unity → 22.unity} +0 -0
- /package/Samples/Example/Scenes/02/{2.unity.meta → 22.unity.meta} +0 -0
- /package/Samples/Example/Scenes/02/{3.unity → 23.unity} +0 -0
- /package/Samples/Example/Scenes/02/{3.unity.meta → 23.unity.meta} +0 -0
- /package/Samples/Example/Scenes/02/{4.unity → 24.unity} +0 -0
- /package/Samples/Example/Scenes/02/{4.unity.meta → 24.unity.meta} +0 -0
- /package/Samples/Example/Scenes/02/{5.unity → 25.unity} +0 -0
- /package/Samples/Example/Scenes/02/{5.unity.meta → 25.unity.meta} +0 -0
- /package/Samples/Example/Scenes/02/{6.unity → 26.unity} +0 -0
- /package/Samples/Example/Scenes/02/{6.unity.meta → 26.unity.meta} +0 -0
- /package/Samples/Example/Scenes/02/{7.unity → 27.unity} +0 -0
- /package/Samples/Example/Scenes/02/{7.unity.meta → 27.unity.meta} +0 -0
- /package/Samples/Example/Scenes/02/{8.unity → 28.unity} +0 -0
- /package/Samples/Example/Scenes/02/{8.unity.meta → 28.unity.meta} +0 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#if UNITY_EDITOR
|
|
2
|
+
using UnityEngine;
|
|
3
|
+
using UnityEditor;
|
|
4
|
+
|
|
5
|
+
namespace jeanf.scenemanagement
|
|
6
|
+
{
|
|
7
|
+
[CustomEditor(typeof(WorldManager))]
|
|
8
|
+
public class WorldManagerEditor : Editor
|
|
9
|
+
{
|
|
10
|
+
public override void OnInspectorGUI()
|
|
11
|
+
{
|
|
12
|
+
DrawDefaultInspector();
|
|
13
|
+
|
|
14
|
+
var worldManager = (WorldManager)target;
|
|
15
|
+
|
|
16
|
+
EditorGUILayout.Space();
|
|
17
|
+
EditorGUILayout.LabelField("Current Player State", EditorStyles.boldLabel);
|
|
18
|
+
|
|
19
|
+
var currentZone = WorldManager.CurrentPlayerZone;
|
|
20
|
+
var currentRegion = WorldManager.CurrentPlayerRegion;
|
|
21
|
+
|
|
22
|
+
EditorGUI.BeginDisabledGroup(true);
|
|
23
|
+
|
|
24
|
+
if (currentZone != null)
|
|
25
|
+
{
|
|
26
|
+
EditorGUILayout.TextField("Current Zone", $"{currentZone.zoneName}");
|
|
27
|
+
}
|
|
28
|
+
else
|
|
29
|
+
{
|
|
30
|
+
EditorGUILayout.TextField("Current Zone", "None");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (currentRegion != null)
|
|
34
|
+
{
|
|
35
|
+
EditorGUILayout.TextField("Current Region", $"{currentRegion.levelName}");
|
|
36
|
+
}
|
|
37
|
+
else
|
|
38
|
+
{
|
|
39
|
+
EditorGUILayout.TextField("Current Region", "None");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
EditorGUI.EndDisabledGroup();
|
|
43
|
+
|
|
44
|
+
if (Application.isPlaying)
|
|
45
|
+
{
|
|
46
|
+
EditorGUILayout.Space();
|
|
47
|
+
if (GUILayout.Button("Debug Zone/Region Info"))
|
|
48
|
+
{
|
|
49
|
+
Debug.Log($"=== WorldManager Debug Info ===");
|
|
50
|
+
Debug.Log($"Current Zone: {(currentZone != null ? $"'{currentZone.zoneName}' (ID: {currentZone.id})" : "None")}");
|
|
51
|
+
Debug.Log($"Current Region: {(currentRegion != null ? $"'{currentRegion.levelName}' (ID: {currentRegion.id})" : "None")}");
|
|
52
|
+
|
|
53
|
+
var zoneCount = worldManager.GetType().GetField("_zoneDictionary",
|
|
54
|
+
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
|
|
55
|
+
?.GetValue(worldManager) as System.Collections.Generic.Dictionary<string, Zone>;
|
|
56
|
+
|
|
57
|
+
var regionCount = worldManager.GetType().GetField("_regionDictionary",
|
|
58
|
+
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
|
|
59
|
+
?.GetValue(worldManager) as System.Collections.Generic.Dictionary<string, Region>;
|
|
60
|
+
|
|
61
|
+
if (zoneCount != null && regionCount != null)
|
|
62
|
+
{
|
|
63
|
+
Debug.Log($"Total zones in dictionary: {zoneCount.Count}");
|
|
64
|
+
Debug.Log($"Total regions in dictionary: {regionCount.Count}");
|
|
65
|
+
|
|
66
|
+
Debug.Log("Available zones:");
|
|
67
|
+
foreach (var zone in zoneCount.Values)
|
|
68
|
+
{
|
|
69
|
+
Debug.Log($" - '{zone.zoneName}' (ID: {zone.id})");
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
Debug.Log("Available regions:");
|
|
73
|
+
foreach (var region in regionCount.Values)
|
|
74
|
+
{
|
|
75
|
+
Debug.Log($" - '{region.levelName}' (ID: {region.id})");
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
#endif
|
|
@@ -12,7 +12,10 @@ namespace jeanf.scenemanagement
|
|
|
12
12
|
{
|
|
13
13
|
public bool isDebug = false;
|
|
14
14
|
private CancellationTokenSource _queueCts;
|
|
15
|
-
[SerializeField] private int maxConcurrentLoads = 2;
|
|
15
|
+
[SerializeField] private int maxConcurrentLoads = 2;
|
|
16
|
+
[SerializeField] private int gcFrameSpread = 5;
|
|
17
|
+
[SerializeField] private bool enableIncrementalGC = true;
|
|
18
|
+
[SerializeField] private float memoryFlushDelay = 0.1f;
|
|
16
19
|
|
|
17
20
|
public delegate void IsLoadingDelegate(bool loadingState);
|
|
18
21
|
public static IsLoadingDelegate IsLoading;
|
|
@@ -49,6 +52,7 @@ namespace jeanf.scenemanagement
|
|
|
49
52
|
|
|
50
53
|
private bool _isProcessingLoadQueue = false;
|
|
51
54
|
private bool _isProcessingUnloadQueue = false;
|
|
55
|
+
private bool _isFlushingMemory = false;
|
|
52
56
|
|
|
53
57
|
private void OnEnable() => Subscribe();
|
|
54
58
|
private void OnDisable() => Unsubscribe();
|
|
@@ -59,6 +63,7 @@ namespace jeanf.scenemanagement
|
|
|
59
63
|
LoadSceneRequest += QueueLoadScene;
|
|
60
64
|
UnLoadSceneRequest += QueueUnloadScene;
|
|
61
65
|
UnloadAllScenesRequest += QueueUnloadAllScenes;
|
|
66
|
+
FlushScenesRequest += () => IncrementalMemoryFlush().Forget();
|
|
62
67
|
}
|
|
63
68
|
|
|
64
69
|
private void Unsubscribe()
|
|
@@ -66,6 +71,7 @@ namespace jeanf.scenemanagement
|
|
|
66
71
|
LoadSceneRequest -= QueueLoadScene;
|
|
67
72
|
UnLoadSceneRequest -= QueueUnloadScene;
|
|
68
73
|
UnloadAllScenesRequest -= QueueUnloadAllScenes;
|
|
74
|
+
FlushScenesRequest = null;
|
|
69
75
|
}
|
|
70
76
|
|
|
71
77
|
private enum SceneOperationType { Load, Unload }
|
|
@@ -84,8 +90,6 @@ namespace jeanf.scenemanagement
|
|
|
84
90
|
|
|
85
91
|
private void QueueUnloadAllScenes()
|
|
86
92
|
{
|
|
87
|
-
if (isDebug) Debug.Log("Unloading all scenes");
|
|
88
|
-
|
|
89
93
|
while (_loadQueue.TryDequeue(out _)) { }
|
|
90
94
|
|
|
91
95
|
_scenesToUnload.Clear();
|
|
@@ -102,14 +106,48 @@ namespace jeanf.scenemanagement
|
|
|
102
106
|
ProcessUnloadQueue().Forget();
|
|
103
107
|
}
|
|
104
108
|
|
|
105
|
-
private async
|
|
109
|
+
private async UniTaskVoid IncrementalMemoryFlush()
|
|
106
110
|
{
|
|
107
|
-
if (
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
+
}
|
|
113
151
|
}
|
|
114
152
|
|
|
115
153
|
private async UniTaskVoid ProcessLoadQueue()
|
|
@@ -191,7 +229,6 @@ namespace jeanf.scenemanagement
|
|
|
191
229
|
await UniTask.WhenAll(_operationBuffer);
|
|
192
230
|
}
|
|
193
231
|
|
|
194
|
-
// Small delay to prevent overwhelming the system
|
|
195
232
|
await UniTask.Yield();
|
|
196
233
|
}
|
|
197
234
|
}
|
|
@@ -199,7 +236,7 @@ namespace jeanf.scenemanagement
|
|
|
199
236
|
{
|
|
200
237
|
if (_loadedScenes.Count == 0)
|
|
201
238
|
{
|
|
202
|
-
|
|
239
|
+
IncrementalMemoryFlush().Forget();
|
|
203
240
|
}
|
|
204
241
|
|
|
205
242
|
_isProcessingUnloadQueue = false;
|
|
@@ -212,11 +249,9 @@ namespace jeanf.scenemanagement
|
|
|
212
249
|
|
|
213
250
|
private async UniTask LoadSceneAsync(string sceneName, CancellationToken cancellationToken)
|
|
214
251
|
{
|
|
215
|
-
AsyncOperation loadOperation = null;
|
|
216
|
-
|
|
217
252
|
try
|
|
218
253
|
{
|
|
219
|
-
loadOperation = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);
|
|
254
|
+
var loadOperation = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);
|
|
220
255
|
loadOperation.allowSceneActivation = true;
|
|
221
256
|
await loadOperation.ToUniTask(cancellationToken: cancellationToken);
|
|
222
257
|
_loadedScenes.Add(sceneName);
|
|
@@ -240,5 +275,44 @@ namespace jeanf.scenemanagement
|
|
|
240
275
|
_processingScenes.Remove(sceneName);
|
|
241
276
|
}
|
|
242
277
|
}
|
|
278
|
+
|
|
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
|
+
public bool IsCurrentlyLoading()
|
|
304
|
+
{
|
|
305
|
+
return _isProcessingLoadQueue || _isProcessingUnloadQueue || _isFlushingMemory;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
public int GetLoadedSceneCount()
|
|
309
|
+
{
|
|
310
|
+
return _loadedScenes.Count;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
public int GetPendingOperationCount()
|
|
314
|
+
{
|
|
315
|
+
return _loadQueue.Count + _unloadQueue.Count;
|
|
316
|
+
}
|
|
243
317
|
}
|
|
244
318
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
using System.Collections.Generic;
|
|
2
|
-
using System.Linq;
|
|
3
2
|
using UnityEngine;
|
|
4
3
|
using jeanf.EventSystem;
|
|
5
4
|
using jeanf.propertyDrawer;
|
|
@@ -14,36 +13,57 @@ namespace jeanf.scenemanagement
|
|
|
14
13
|
public bool isDebug = false;
|
|
15
14
|
private SceneLoader _sceneLoader;
|
|
16
15
|
public List<Region> ListOfRegions;
|
|
16
|
+
|
|
17
17
|
private Dictionary<string, Zone> _zoneDictionary = new Dictionary<string, Zone>();
|
|
18
18
|
private Dictionary<string, Region> _regionDictionary = new Dictionary<string, Region>();
|
|
19
19
|
private Dictionary<string, Region> _regionDictionaryPerZone = new Dictionary<string, Region>();
|
|
20
|
-
private Dictionary<Collider, Region> _regionDictionaryPerCollider = new Dictionary<Collider, Region>();
|
|
21
20
|
private Dictionary<string, List<SceneReference>> _dependenciesPerRegion = new Dictionary<string, List<SceneReference>>();
|
|
21
|
+
private Dictionary<string, List<string>> _compiledSceneLists = new Dictionary<string, List<string>>();
|
|
22
|
+
private HashSet<string> _landingZoneIds = new HashSet<string>();
|
|
22
23
|
|
|
23
24
|
private List<Region> _activeRegions = new List<Region>();
|
|
24
|
-
private
|
|
25
|
+
private bool _mappingInitialized = false;
|
|
26
|
+
|
|
27
|
+
private List<string> _tempSceneNames = new List<string>();
|
|
28
|
+
private List<Region> _tempRegionsToRemove = new List<Region>();
|
|
25
29
|
|
|
26
30
|
[SerializeField] private StringEventChannelSO regionChangeRequestChannel;
|
|
27
31
|
[SerializeField] private SendTeleportTarget sendTeleportTarget;
|
|
28
32
|
|
|
29
33
|
[ReadOnly] [SerializeField] private Zone _currentPlayerZone;
|
|
34
|
+
[ReadOnly] [SerializeField] private Region _currentPlayerRegion;
|
|
35
|
+
|
|
30
36
|
private static WorldManager Instance;
|
|
37
|
+
private static bool _isRegionTransitioning = false;
|
|
38
|
+
|
|
31
39
|
public static Zone CurrentPlayerZone
|
|
32
40
|
{
|
|
33
|
-
get => Instance
|
|
34
|
-
private set
|
|
41
|
+
get => Instance?._currentPlayerZone;
|
|
42
|
+
private set
|
|
43
|
+
{
|
|
44
|
+
if (Instance != null)
|
|
45
|
+
{
|
|
46
|
+
Instance._currentPlayerZone = value;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
35
49
|
}
|
|
36
50
|
|
|
37
|
-
[ReadOnly] [SerializeField] private Region _currentPlayerRegion;
|
|
38
51
|
public static Region CurrentPlayerRegion
|
|
39
52
|
{
|
|
40
|
-
get => Instance
|
|
41
|
-
private set
|
|
53
|
+
get => Instance?._currentPlayerRegion;
|
|
54
|
+
private set
|
|
55
|
+
{
|
|
56
|
+
if (Instance != null)
|
|
57
|
+
{
|
|
58
|
+
Instance._currentPlayerRegion = value;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
42
61
|
}
|
|
43
62
|
|
|
63
|
+
public static bool IsRegionTransitioning => _isRegionTransitioning;
|
|
64
|
+
|
|
44
65
|
public delegate void SendId(string newRegionID);
|
|
45
66
|
public static SendId RequestRegionChange;
|
|
46
|
-
|
|
47
67
|
public static SendId PublishCurrentRegionId;
|
|
48
68
|
public static SendId PublishCurrentZoneId;
|
|
49
69
|
|
|
@@ -54,7 +74,8 @@ namespace jeanf.scenemanagement
|
|
|
54
74
|
public static BroadcastAppList _broadcastAppList;
|
|
55
75
|
|
|
56
76
|
private bool hasGameBeenInitialized = false;
|
|
57
|
-
|
|
77
|
+
private string _lastNotifiedZone = "";
|
|
78
|
+
private string _lastNotifiedRegion = "";
|
|
58
79
|
|
|
59
80
|
private void Awake()
|
|
60
81
|
{
|
|
@@ -71,7 +92,6 @@ namespace jeanf.scenemanagement
|
|
|
71
92
|
{
|
|
72
93
|
regionChangeRequestChannel.OnEventRaised += OnRegionChange;
|
|
73
94
|
RequestRegionChange += OnRegionChange;
|
|
74
|
-
|
|
75
95
|
ResetWorld += Init;
|
|
76
96
|
ScenarioManager.OnZoneOverridesChanged += OnZoneOverridesChanged;
|
|
77
97
|
}
|
|
@@ -80,112 +100,214 @@ namespace jeanf.scenemanagement
|
|
|
80
100
|
{
|
|
81
101
|
regionChangeRequestChannel.OnEventRaised -= OnRegionChange;
|
|
82
102
|
RequestRegionChange -= OnRegionChange;
|
|
83
|
-
|
|
84
103
|
ResetWorld -= Init;
|
|
85
104
|
ScenarioManager.OnZoneOverridesChanged -= OnZoneOverridesChanged;
|
|
86
105
|
}
|
|
87
106
|
|
|
88
|
-
|
|
89
107
|
private void Init()
|
|
90
108
|
{
|
|
91
|
-
if(isDebug) Debug.Log($"[WorldManager] World reset.");
|
|
92
109
|
hasGameBeenInitialized = false;
|
|
110
|
+
_currentPlayerZone = null;
|
|
111
|
+
_currentPlayerRegion = null;
|
|
112
|
+
_lastNotifiedZone = "";
|
|
113
|
+
_lastNotifiedRegion = "";
|
|
114
|
+
_isRegionTransitioning = false;
|
|
115
|
+
|
|
116
|
+
ClearAllMappings();
|
|
117
|
+
BuildDataMappings();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
private void ClearAllMappings()
|
|
121
|
+
{
|
|
122
|
+
_zoneDictionary.Clear();
|
|
123
|
+
_regionDictionary.Clear();
|
|
124
|
+
_regionDictionaryPerZone.Clear();
|
|
125
|
+
_dependenciesPerRegion.Clear();
|
|
126
|
+
_compiledSceneLists.Clear();
|
|
127
|
+
_landingZoneIds.Clear();
|
|
128
|
+
_activeRegions.Clear();
|
|
129
|
+
_tempSceneNames.Clear();
|
|
130
|
+
_tempRegionsToRemove.Clear();
|
|
131
|
+
_mappingInitialized = false;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
private void BuildDataMappings()
|
|
135
|
+
{
|
|
136
|
+
if (_mappingInitialized) return;
|
|
137
|
+
|
|
138
|
+
var regionCount = ListOfRegions?.Count ?? 0;
|
|
139
|
+
if (regionCount == 0) return;
|
|
140
|
+
|
|
93
141
|
foreach (var region in ListOfRegions)
|
|
94
142
|
{
|
|
95
|
-
|
|
96
|
-
if(
|
|
97
|
-
|
|
143
|
+
if (region == null) continue;
|
|
144
|
+
if (!_regionDictionary.TryAdd(region.id, region)) continue;
|
|
145
|
+
|
|
146
|
+
_dependenciesPerRegion.TryAdd(region.id, region.dependenciesInThisRegion);
|
|
147
|
+
PrecompileSceneList(region);
|
|
98
148
|
|
|
99
|
-
|
|
100
|
-
foreach (var scenario in region.scenariosInThisRegion)
|
|
149
|
+
if (region.scenariosInThisRegion != null)
|
|
101
150
|
{
|
|
102
|
-
|
|
103
|
-
|
|
151
|
+
foreach (var scenario in region.scenariosInThisRegion)
|
|
152
|
+
{
|
|
153
|
+
if (scenario != null)
|
|
154
|
+
{
|
|
155
|
+
ScenarioManager.ScenarioDictionary.TryAdd(scenario.id, scenario);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
104
158
|
}
|
|
105
159
|
|
|
106
|
-
|
|
107
|
-
foreach (var zone in region.zonesInThisRegion)
|
|
160
|
+
if (region.zonesInThisRegion != null)
|
|
108
161
|
{
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
162
|
+
foreach (var zone in region.zonesInThisRegion)
|
|
163
|
+
{
|
|
164
|
+
if (zone != null)
|
|
165
|
+
{
|
|
166
|
+
_zoneDictionary.TryAdd(zone.id, zone);
|
|
167
|
+
_regionDictionaryPerZone.TryAdd(zone.id, region);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
BuildLandingZoneCache();
|
|
174
|
+
_mappingInitialized = true;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
private void PrecompileSceneList(Region region)
|
|
178
|
+
{
|
|
179
|
+
var sceneNames = new List<string>(region.dependenciesInThisRegion.Count);
|
|
180
|
+
foreach (var dependency in region.dependenciesInThisRegion)
|
|
181
|
+
{
|
|
182
|
+
sceneNames.Add(dependency.SceneName);
|
|
183
|
+
}
|
|
184
|
+
_compiledSceneLists[region.id] = sceneNames;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
private void BuildLandingZoneCache()
|
|
188
|
+
{
|
|
189
|
+
var connectivity = FindObjectOfType<RegionConnectivityAuthoring>();
|
|
190
|
+
if (connectivity?.regionConnectivity?.landingZones == null) return;
|
|
191
|
+
|
|
192
|
+
foreach (var landing in connectivity.regionConnectivity.landingZones)
|
|
193
|
+
{
|
|
194
|
+
if (landing?.landingZone != null)
|
|
195
|
+
{
|
|
196
|
+
_landingZoneIds.Add(landing.landingZone.id);
|
|
197
|
+
}
|
|
117
198
|
}
|
|
118
199
|
}
|
|
119
200
|
|
|
120
201
|
public static void NotifyZoneChangeFromECS(string zoneId)
|
|
121
202
|
{
|
|
122
|
-
if (Instance != null)
|
|
203
|
+
if (Instance != null && !_isRegionTransitioning)
|
|
123
204
|
{
|
|
124
205
|
Instance.OnZoneChangedFromECS(zoneId);
|
|
125
206
|
}
|
|
126
207
|
}
|
|
208
|
+
|
|
209
|
+
public static void NotifyRegionChangeFromECS(string regionId)
|
|
210
|
+
{
|
|
211
|
+
if (Instance != null && !_isRegionTransitioning)
|
|
212
|
+
{
|
|
213
|
+
Instance.OnRegionChangedFromECS(regionId);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
127
216
|
|
|
128
217
|
private void OnZoneChangedFromECS(string zoneId)
|
|
129
218
|
{
|
|
219
|
+
if (string.IsNullOrEmpty(zoneId) || _lastNotifiedZone == zoneId) return;
|
|
220
|
+
|
|
130
221
|
if (!_zoneDictionary.TryGetValue(zoneId, out var zone)) return;
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
222
|
+
|
|
223
|
+
_lastNotifiedZone = zoneId;
|
|
224
|
+
_currentPlayerZone = zone;
|
|
225
|
+
|
|
226
|
+
PublishCurrentZoneId?.Invoke(zone.id);
|
|
134
227
|
PublishAppList(zone);
|
|
135
|
-
|
|
136
|
-
var newRegion = _regionDictionaryPerZone[zone.id.id];
|
|
137
|
-
if(newRegion != CurrentPlayerRegion) OnRegionChange(newRegion);
|
|
138
228
|
}
|
|
229
|
+
|
|
230
|
+
private void OnRegionChangedFromECS(string regionId)
|
|
231
|
+
{
|
|
232
|
+
if (string.IsNullOrEmpty(regionId) || _lastNotifiedRegion == regionId) return;
|
|
233
|
+
|
|
234
|
+
if (!_regionDictionary.TryGetValue(regionId, out var region)) return;
|
|
235
|
+
|
|
236
|
+
_lastNotifiedRegion = regionId;
|
|
237
|
+
_currentPlayerRegion = region;
|
|
238
|
+
|
|
239
|
+
OnRegionChange(region);
|
|
240
|
+
}
|
|
241
|
+
|
|
139
242
|
private void OnZoneOverridesChanged(string zoneId)
|
|
140
243
|
{
|
|
141
|
-
|
|
142
|
-
if (CurrentPlayerZone.id == zoneId)
|
|
244
|
+
if (CurrentPlayerZone != null && CurrentPlayerZone.id == zoneId)
|
|
143
245
|
{
|
|
144
246
|
PublishAppList(CurrentPlayerZone);
|
|
145
247
|
}
|
|
146
248
|
}
|
|
147
249
|
|
|
148
|
-
private void SetCurrentZoneAndRegion(GameObject gameObject, Zone zone)
|
|
149
|
-
{
|
|
150
|
-
if (!gameObject.CompareTag("Player")) return;
|
|
151
|
-
CurrentPlayerZone = zone;
|
|
152
|
-
PublishCurrentZoneId?.Invoke(zone.id);
|
|
153
|
-
PublishAppList(zone);
|
|
154
|
-
var newRegion = _regionDictionaryPerZone[zone.id];
|
|
155
|
-
if(newRegion != CurrentPlayerRegion) OnRegionChange(newRegion);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
250
|
private void OnRegionChange(string newRegionID)
|
|
159
251
|
{
|
|
160
252
|
if (!_regionDictionary.TryGetValue(newRegionID, out var region)) return;
|
|
161
253
|
OnRegionChange(region);
|
|
162
254
|
}
|
|
163
255
|
|
|
164
|
-
// ReSharper disable Unity.PerformanceAnalysis
|
|
165
256
|
private void OnRegionChange(Region region)
|
|
166
257
|
{
|
|
167
|
-
|
|
168
|
-
|
|
258
|
+
_isRegionTransitioning = true;
|
|
259
|
+
|
|
260
|
+
_currentPlayerRegion = region;
|
|
261
|
+
_lastNotifiedRegion = region.id;
|
|
262
|
+
|
|
263
|
+
PublishCurrentRegionId?.Invoke(_currentPlayerRegion.id);
|
|
169
264
|
|
|
170
|
-
|
|
171
|
-
var
|
|
265
|
+
_tempRegionsToRemove.Clear();
|
|
266
|
+
foreach (var activeRegion in _activeRegions)
|
|
267
|
+
{
|
|
268
|
+
var removedRegion = RequestUnLoadForObsoleteRegion(activeRegion);
|
|
269
|
+
_tempRegionsToRemove.Add(removedRegion);
|
|
270
|
+
}
|
|
172
271
|
|
|
173
|
-
foreach (var r in
|
|
272
|
+
foreach (var r in _tempRegionsToRemove)
|
|
174
273
|
{
|
|
175
274
|
_activeRegions.Remove(r);
|
|
176
275
|
}
|
|
177
276
|
|
|
178
277
|
RequestLoadForRegionDependencies(region);
|
|
179
278
|
|
|
180
|
-
// set teleporting position
|
|
181
279
|
var spawnPos = SetTeleportTarget(region, hasGameBeenInitialized);
|
|
182
|
-
sendTeleportTarget.transform.position = spawnPos.position;
|
|
183
|
-
sendTeleportTarget.transform.rotation = Quaternion.Euler(spawnPos.rotation);
|
|
184
|
-
// teleport!
|
|
185
|
-
sendTeleportTarget.Teleport();
|
|
186
280
|
|
|
187
|
-
|
|
281
|
+
if (sendTeleportTarget != null)
|
|
282
|
+
{
|
|
283
|
+
sendTeleportTarget.transform.position = spawnPos.position;
|
|
284
|
+
sendTeleportTarget.transform.rotation = Quaternion.Euler(spawnPos.rotation);
|
|
285
|
+
sendTeleportTarget.Teleport();
|
|
286
|
+
}
|
|
287
|
+
|
|
188
288
|
_activeRegions.Add(region);
|
|
289
|
+
|
|
290
|
+
StartCoroutine(CompleteRegionTransition());
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
private System.Collections.IEnumerator CompleteRegionTransition()
|
|
294
|
+
{
|
|
295
|
+
yield return new WaitForEndOfFrame();
|
|
296
|
+
yield return new WaitForEndOfFrame();
|
|
297
|
+
|
|
298
|
+
_isRegionTransitioning = false;
|
|
299
|
+
|
|
300
|
+
if (_currentPlayerRegion?.zonesInThisRegion != null && _currentPlayerRegion.zonesInThisRegion.Count > 0)
|
|
301
|
+
{
|
|
302
|
+
var firstZone = _currentPlayerRegion.zonesInThisRegion[0];
|
|
303
|
+
if (firstZone != null)
|
|
304
|
+
{
|
|
305
|
+
_currentPlayerZone = firstZone;
|
|
306
|
+
_lastNotifiedZone = firstZone.id;
|
|
307
|
+
PublishCurrentZoneId?.Invoke(firstZone.id);
|
|
308
|
+
PublishAppList(firstZone);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
189
311
|
}
|
|
190
312
|
|
|
191
313
|
private SpawnPos SetTeleportTarget(Region region, bool hasRegionBeenInitialized)
|
|
@@ -203,39 +325,59 @@ namespace jeanf.scenemanagement
|
|
|
203
325
|
private void PublishAppList(Zone zone)
|
|
204
326
|
{
|
|
205
327
|
var listToBroadcast = zone.DefaultAppsInZone;
|
|
206
|
-
if(isDebug) Debug.Log($"[WorldManager] Default list for zone [{zone.name}] : [{string.Join(", ", listToBroadcast)}]");
|
|
207
|
-
// check if for this zone there is no override
|
|
208
328
|
if (ScenarioManager.activeOverridesPerZone.TryGetValue(zone.id, out var value))
|
|
209
329
|
{
|
|
210
|
-
// if yes, send override list
|
|
211
330
|
listToBroadcast = value;
|
|
212
|
-
if(isDebug) Debug.Log($"[WorldManager] List override found for zone [{zone.name}] : [{string.Join(", ", listToBroadcast)}]");
|
|
213
331
|
}
|
|
214
332
|
|
|
215
|
-
// broadcast list
|
|
216
333
|
_broadcastAppList?.Invoke(listToBroadcast);
|
|
217
334
|
}
|
|
218
335
|
|
|
219
336
|
private void RequestLoadForRegionDependencies(Region region)
|
|
220
337
|
{
|
|
221
|
-
if (
|
|
222
|
-
|
|
338
|
+
if (!_compiledSceneLists.TryGetValue(region.id, out var sceneNames) || sceneNames.Count <= 0) return;
|
|
339
|
+
|
|
340
|
+
foreach (var sceneName in sceneNames)
|
|
223
341
|
{
|
|
224
|
-
_sceneLoader.LoadSceneRequest(
|
|
342
|
+
_sceneLoader.LoadSceneRequest(sceneName);
|
|
225
343
|
}
|
|
226
344
|
}
|
|
345
|
+
|
|
227
346
|
private Region RequestUnLoadForObsoleteRegion(Region region)
|
|
228
347
|
{
|
|
229
|
-
|
|
348
|
+
if (_compiledSceneLists.TryGetValue(region.id, out var sceneNames))
|
|
230
349
|
{
|
|
231
|
-
|
|
350
|
+
foreach (var sceneName in sceneNames)
|
|
351
|
+
{
|
|
352
|
+
_sceneLoader.UnLoadSceneRequest(sceneName);
|
|
353
|
+
}
|
|
232
354
|
}
|
|
233
355
|
return region;
|
|
234
356
|
}
|
|
235
|
-
|
|
236
|
-
|
|
357
|
+
|
|
358
|
+
public bool IsLandingZone(string zoneId)
|
|
359
|
+
{
|
|
360
|
+
return _landingZoneIds.Contains(zoneId);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
public HashSet<string> GetLandingZoneIds()
|
|
364
|
+
{
|
|
365
|
+
return _landingZoneIds;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
public static Dictionary<string, Zone> GetZoneDictionary()
|
|
369
|
+
{
|
|
370
|
+
return Instance?._zoneDictionary;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
public static Dictionary<string, Region> GetRegionDictionary()
|
|
374
|
+
{
|
|
375
|
+
return Instance?._regionDictionary;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
public static Dictionary<string, Region> GetRegionDictionaryPerZone()
|
|
237
379
|
{
|
|
238
|
-
return
|
|
380
|
+
return Instance?._regionDictionaryPerZone;
|
|
239
381
|
}
|
|
240
382
|
}
|
|
241
383
|
}
|