-
Notifications
You must be signed in to change notification settings - Fork 37
Expand file tree
/
Copy pathAddressableSceneHandler.cs
More file actions
171 lines (148 loc) · 7.43 KB
/
AddressableSceneHandler.cs
File metadata and controls
171 lines (148 loc) · 7.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
// This script will only compile if the HAS_ADDRESSABLES symbol is defined.
#if HAS_ADDRESSABLES
using System.Collections.Generic;
using UnityEngine.SceneManagement;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.ResourceManagement.ResourceProviders;
using UnityEngine;
using Netick.Unity;
namespace Netick.Samples
{
[AddComponentMenu("Netick/Addressable Scene Handler")]
public class AddressableSceneHandler : NetworkSceneHandler
{
private class AddressableSceneOperation : ISceneOperation
{
AsyncOperationHandle<SceneInstance> Handle;
bool ISceneOperation.IsDone => Handle.IsDone;
float ISceneOperation.Progress => Handle.PercentComplete;
public AddressableSceneOperation (AsyncOperationHandle<SceneInstance> handle)
{
Handle = handle;
}
}
public string[] AddressableScenes = new string[0];
public override int CustomScenesCount => AddressableScenes != null ? AddressableScenes.Length : 0;
private Dictionary<string, int> _keyToIndex;
private Dictionary<int, string> _indexToKey;
private Dictionary<Scene, SceneInstance> _loadedScenes;
private void Awake()
{
_keyToIndex = new(AddressableScenes.Length);
_indexToKey = new(AddressableScenes.Length);
_loadedScenes = new(AddressableScenes.Length);
for (int i = 0; i < AddressableScenes.Length; i++)
{
_keyToIndex.Add(AddressableScenes[i], i);
_indexToKey.Add(i, AddressableScenes[i]);
}
}
protected override ISceneOperation LoadCustomSceneAsync (int index, LoadSceneParameters loadSceneParameters, out string sceneName)
{
var key = _indexToKey[index];
sceneName = key;
var handle = Addressables.LoadSceneAsync(key, loadSceneParameters);
handle.Completed += handle =>
{
if (handle.Status == AsyncOperationStatus.Succeeded)
_loadedScenes.Add(handle.Result.Scene, handle.Result);
else
Sandbox.LogError($"Addressables.LoadSceneAsync: failed to load an addressable scene {handle.DebugName}");
};
return new AddressableSceneOperation(handle);
}
protected override ISceneOperation UnloadCustomSceneAsync (Scene scene)
{
var didGetSceneInstance = _loadedScenes.TryGetValue(scene, out var sceneInstance);
if (!didGetSceneInstance || !scene.IsValid())
{
Sandbox.LogError($"Unloading scene: couldn't find a scene to unload {scene.name}");
return null;
}
var handle = Addressables.UnloadSceneAsync(sceneInstance);
handle.Completed += handle =>
{
if (handle.Status == AsyncOperationStatus.Succeeded)
_loadedScenes.Remove(handle.Result.Scene);
else
Sandbox.LogError($"Addressables.UnloadSceneAsync: failed to unload scene {scene.name}");
};
return new AddressableSceneOperation (handle);
}
// -- Addressable Scenes
public void LoadAddressableSceneAsync(string key, LoadSceneMode loadSceneMode)
{
if (_keyToIndex.TryGetValue(key, out int customIndex))
Sandbox.LoadCustomSceneAsync(customIndex, new LoadSceneParameters(loadSceneMode, Sandbox.GetDefaultPhysicsMode()));
else
Sandbox.LogError("Loading scene: failed to find the addressable scene key in the AddressableScenes array. Make sure to add all scenes keys to the array.");
}
public void LoadAddressableSceneAsync(string key, LoadSceneParameters loadSceneParameters)
{
if (_keyToIndex.TryGetValue(key, out int customIndex))
Sandbox.LoadCustomSceneAsync(customIndex, loadSceneParameters);
else
Sandbox.LogError("Loading scene: failed to find the addressable scene key in the AddressableScenes array. Make sure to add all scenes keys to the array.");
}
public void UnloadAddressableSceneAsync(string key)
{
if (_keyToIndex.TryGetValue(key, out int customIndex))
Sandbox.UnloadSceneAsync(customIndex);
else
Sandbox.LogError("Unloading scene: failed to find the addressable scene key in the AddressableScenes array. Make sure to add all scenes keys to the array.");
}
public void UnloadAddressableSceneAsync(Scene scene)
{
Sandbox.UnloadSceneAsync(scene);
}
// -- Build Scenes
// NetworkSceneHandler already implements exactly the code shown here, the reason we still included it in here is for demonstration purposes.
protected override ISceneOperation LoadBuildSceneAsync (int buildIndex, LoadSceneParameters loadSceneParameters) => new BuildSceneOperation(SceneManager.LoadSceneAsync(buildIndex, loadSceneParameters));
protected override ISceneOperation UnloadBuildSceneAsync (Scene scene) => new BuildSceneOperation(SceneManager.UnloadSceneAsync(scene));
}
public static class AddressableSceneHandlerSandboxExtensions
{
/// <summary>
/// <i><b>[Server Only]</b></i> Loads an addressable scene asynchronously using a key.
/// </summary>
public static void LoadAddressableSceneAsync(this NetworkSandbox sandbox, string key, LoadSceneMode loadSceneMode)
{
if (sandbox.TryGetComponent<AddressableSceneHandler>(out var defaultSceneHandler))
defaultSceneHandler.LoadAddressableSceneAsync(key, loadSceneMode);
else
sandbox.LogError($"{nameof(AddressableSceneHandler)} is not added to the sandbox. Make sure to add {nameof(AddressableSceneHandler)} to your sandbox prefab.");
}
/// <summary>
/// <i><b>[Server Only]</b></i> Loads an addressable scene asynchronously using a key.
/// </summary>
public static void LoadAddressableSceneAsync(this NetworkSandbox sandbox, string key, LoadSceneParameters loadSceneParameters)
{
if (sandbox.TryGetComponent<AddressableSceneHandler>(out var defaultSceneHandler))
defaultSceneHandler.LoadAddressableSceneAsync(key, loadSceneParameters);
else
sandbox.LogError($"{nameof(AddressableSceneHandler)} is not added to the sandbox. Make sure to add {nameof(AddressableSceneHandler)} to your sandbox prefab.");
}
/// <summary>
/// <i><b>[Server Only]</b></i> Unloads an addressable scene asynchronously using a key.
/// </summary>
public static void UnloadAddressableSceneAsync(this NetworkSandbox sandbox, string key)
{
if (sandbox.TryGetComponent<AddressableSceneHandler>(out var defaultSceneHandler))
defaultSceneHandler.UnloadAddressableSceneAsync(key);
else
sandbox.LogError($"{nameof(AddressableSceneHandler)} is not added to the sandbox. Make sure to add {nameof(AddressableSceneHandler)} to your sandbox prefab.");
}
/// <summary>
/// <i><b>[Server Only]</b></i> Unloads an addressable scene asynchronously using a Scene struct.
/// </summary>
public static void UnloadAddressableSceneAsync(this NetworkSandbox sandbox, Scene scene)
{
if (sandbox.TryGetComponent<AddressableSceneHandler>(out var defaultSceneHandler))
defaultSceneHandler.UnloadAddressableSceneAsync(scene);
else
sandbox.LogError($"{nameof(AddressableSceneHandler)} is not added to the sandbox. Make sure to add {nameof(AddressableSceneHandler)} to your sandbox prefab.");
}
}
}
#endif