diff --git a/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs b/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs index 331d5ff112..c379b80b85 100644 --- a/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs +++ b/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs @@ -525,6 +525,16 @@ internal bool RemoveServerClientSceneHandle(int serverHandle, int clientHandle) /// internal Dictionary BuildIndexToHash = new Dictionary(); + /// + /// Hash to external scene path lookup table + /// + internal Dictionary HashToAddressableKey = new Dictionary(); + + /// + /// External scene name to hash lookup table + /// + internal Dictionary AddressableKeyToHash = new Dictionary(); + /// /// The Condition: While a scene is asynchronously loaded in single loading scene mode, if any new NetworkObjects are spawned /// they need to be moved into the do not destroy temporary scene @@ -668,8 +678,8 @@ internal bool ShouldDeferCreateObject() /// internal string GetSceneNameFromPath(string scenePath) { - var begin = scenePath.LastIndexOf("/", StringComparison.Ordinal) + 1; - var end = scenePath.LastIndexOf(".", StringComparison.Ordinal); + var begin = scenePath.Contains("/") ? scenePath.LastIndexOf("/", StringComparison.Ordinal) + 1 : 0; + var end = scenePath.Contains(".") ? scenePath.LastIndexOf(".", StringComparison.Ordinal) : scenePath.Length; return scenePath.Substring(begin, end - begin); } @@ -706,6 +716,17 @@ internal void GenerateScenesInBuild() } } + /// + /// Register scene that is preloaded from Addressable + /// + /// The addressable runtime key of the scene + public void RegisterAddressableScene(string addressableKey) + { + var hash = XXHash.Hash32(addressableKey); + HashToAddressableKey[hash] = addressableKey; + AddressableKeyToHash[addressableKey] = hash; + } + /// /// Gets the scene name from a hash value generated from the full scene path /// @@ -727,7 +748,17 @@ internal string SceneNameFromHash(uint sceneHash) /// internal string ScenePathFromHash(uint sceneHash) { - if (HashToBuildIndex.ContainsKey(sceneHash)) + if (HashToAddressableKey.TryGetValue(sceneHash, out var externalScenePath)) + { +#if UNITY_EDITOR + if (Guid.TryParse(externalScenePath, out var guid)) + { + externalScenePath = UnityEditor.AssetDatabase.GUIDToAssetPath(guid.ToString("N")); + } +#endif + return externalScenePath; + } + else if (HashToBuildIndex.ContainsKey(sceneHash)) { return SceneUtility.GetScenePathByBuildIndex(HashToBuildIndex[sceneHash]); } @@ -743,6 +774,19 @@ internal string ScenePathFromHash(uint sceneHash) /// internal uint SceneHashFromNameOrPath(string sceneNameOrPath) { +#if UNITY_EDITOR + var addressableKey = UnityEditor.AssetDatabase.AssetPathToGUID(sceneNameOrPath); + + if (AddressableKeyToHash.TryGetValue(addressableKey, out var addressableHash)) + { + return addressableHash; + } +#endif + if (AddressableKeyToHash.TryGetValue(sceneNameOrPath, out var externalSceneHash)) + { + return externalSceneHash; + } + var buildIndex = SceneUtility.GetBuildIndexByScenePath(sceneNameOrPath); if (buildIndex >= 0) { @@ -2036,10 +2080,7 @@ internal void SynchronizeNetworkObjects(ulong clientId, bool synchronizingServic sceneEventData.LoadSceneMode = ClientSynchronizationMode; var activeScene = SceneManager.GetActiveScene(); sceneEventData.SceneEventType = SceneEventType.Synchronize; - if (BuildIndexToHash.ContainsKey(activeScene.buildIndex)) - { - sceneEventData.ActiveSceneHash = BuildIndexToHash[activeScene.buildIndex]; - } + sceneEventData.ActiveSceneHash = SceneHashFromNameOrPath(activeScene.path); // Organize how (and when) we serialize our NetworkObjects for (int i = 0; i < SceneManager.sceneCount; i++) @@ -2375,13 +2416,10 @@ private void HandleClientSceneEvent(uint sceneEventId) PopulateScenePlacedObjects(DontDestroyOnLoadScene, false); // If needed, set the currently active scene - if (HashToBuildIndex.ContainsKey(sceneEventData.ActiveSceneHash)) + var targetActiveScene = SceneManager.GetSceneByName(SceneNameFromHash(sceneEventData.ActiveSceneHash)); + if (targetActiveScene.isLoaded && targetActiveScene.handle != SceneManager.GetActiveScene().handle) { - var targetActiveScene = SceneManager.GetSceneByBuildIndex(HashToBuildIndex[sceneEventData.ActiveSceneHash]); - if (targetActiveScene.isLoaded && targetActiveScene.handle != SceneManager.GetActiveScene().handle) - { - SceneManager.SetActiveScene(targetActiveScene); - } + SceneManager.SetActiveScene(targetActiveScene); } // Spawn and Synchronize all NetworkObjects diff --git a/com.unity.netcode.gameobjects/package.json b/com.unity.netcode.gameobjects/package.json index b8b6581016..f4e1775155 100644 --- a/com.unity.netcode.gameobjects/package.json +++ b/com.unity.netcode.gameobjects/package.json @@ -4,6 +4,9 @@ "description": "Netcode for GameObjects is a high-level netcode SDK that provides networking capabilities to GameObject/MonoBehaviour workflows within Unity and sits on top of underlying transport layer.", "version": "2.3.0", "unity": "6000.0", + "author": { + "name": "Unity" + }, "dependencies": { "com.unity.nuget.mono-cecil": "1.11.4", "com.unity.transport": "2.4.0"