-
Notifications
You must be signed in to change notification settings - Fork 449
Addressables Scene Loading support #423
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
curious about this. an no update since created. What is the option / path here? to not use networkscenemanager? |
We have compatibility with much of addressable (see `NetworkManager.AddNetworkPrefab), but unfortunately this does not include addressable scene loading. This functionality isn't in our near-term plans for the SDK, but we'd be happy to have a discussion about possible approaches if anyone from the community wants to contribute a solution. |
So is there actually a way to do that? |
Yes there is @NatureRaph ! We allowed extension of the NetworkSceneManager in our fork of NGO 1.1: fork Have a look at these files in the commit:
And implemented the addressable scene loading in our codebase like this: AddressablesSceneManagerHandler.cs using System;
using System.Collections.Generic;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.ResourceManagement.ResourceProviders;
using UnityEngine.SceneManagement;
public class AddressablesSceneManagerHandler : ISceneManagerHandler
{
private readonly Dictionary<string, AsyncOperationHandle<SceneInstance>> loadOperationHandles = new Dictionary<string, AsyncOperationHandle<SceneInstance>>();
public AddressablesSceneManagerHandler() => SceneManager.sceneLoaded += RemoveOperationHandle;
~AddressablesSceneManagerHandler() => SceneManager.sceneLoaded -= RemoveOperationHandle;
private void RemoveOperationHandle(Scene scene, LoadSceneMode loadSceneMode)
{
if (loadSceneMode == LoadSceneMode.Single)
{
loadOperationHandles.Remove(scene.name);
}
}
public AsyncOperationHandle<SceneInstance> PreloadSceneAsync(string sceneName, LoadSceneMode loadSceneMode) =>
loadOperationHandles[sceneName] = Addressables.LoadSceneAsync(sceneName, loadSceneMode, activateOnLoad: false);
public AsyncOperation LoadSceneAsync(string sceneName, LoadSceneMode loadSceneMode, SceneEventProgress sceneEventProgress)
{
var activated = false;
var hook = sceneEventProgress.GetAsyncOperationCompletionHook(check: () => activated);
LoadSceneAsync(sceneName, loadSceneMode, onActivated: () =>
{
activated = true;
hook?.Invoke();
});
return null;
}
public AsyncOperation LoadSceneAsync(string sceneName, LoadSceneMode loadSceneMode, Action onActivated = null)
{
if (!loadOperationHandles.TryGetValue(sceneName, out var loadOperationHandle))
{
loadOperationHandle = PreloadSceneAsync(sceneName, loadSceneMode);
}
loadOperationHandle.Completed += operationHandle =>
operationHandle.Result.ActivateAsync().completed += _ => onActivated?.Invoke();
return null;
}
public AsyncOperation UnloadSceneAsync(Scene scene, SceneEventProgress sceneEventProgress)
{
if (loadOperationHandles.TryGetValue(scene.name, out var loadOperationHandle))
{
var unloadOperationHandle = Addressables.UnloadSceneAsync(loadOperationHandle);
unloadOperationHandle.Completed += _ =>
sceneEventProgress.GetAsyncOperationCompletionHook(check: () => unloadOperationHandle.IsDone).Invoke();
loadOperationHandles.Remove(scene.name);
}
return null;
}
} You can register your addressable scenes this way: /// <summary>
/// Should be executed immediately after starting the NetworkManager as Server, Host or Client.
/// </summary>
public IEnumerator SetupAddressableSceneLoading()
{
var sceneManager = NetworkManager.SceneManager;
sceneManager.SceneManagerHandler = new AddressablesSceneManagerHandler();
var operationHandle = Addressables.LoadResourceLocationsAsync(ADDRESSABLES_SCENES_LABEL);
yield return operationHandle;
if (operationHandle.Status == AsyncOperationStatus.Succeeded)
{
sceneManager.RegisterExternalScenes(
operationHandle.Result.Select(location => location.InternalId).ToArray());
}
Addressables.Release(operationHandle);
} P.S. With this AddressablesSceneManagerHandler, you can even do scene preloading on the client-side by sending an RPC to the client prior to doing a networked scene loading on the host/server that will call PreloadSceneAsync. This will effectively parallelize the addressable loading and only sequence the activation of the scenes resulting in a total scene loading time of 1.1x a non-networked scene loading (instead of the usual 2x time due to the host/server normally loading its scene completely before asking the clients to do so). P.P.S. The addressable keys/names of the scenes have to be the same as their scene name and their Internal Asset Naming Mode must be set to Full Path, like this: Hope it helps! 😄 |
Thank you very much |
So if I unterstand correctly, I have to download those scripts and add them, right? But the NetworkSceneManager has 314 Errors |
currently SwitchScene(server) and OnSceneSwitch(client) in NetworkSceneManager directly use SceneManager.LoadSceneAsync,
is there any plan to support addressable load scene?
The text was updated successfully, but these errors were encountered: