From aef40f8e38585371b9ac482c31db43f9135d9d79 Mon Sep 17 00:00:00 2001 From: JulianMKhoo Date: Thu, 25 Jun 2026 10:46:48 +0700 Subject: [PATCH 1/3] fix: scene handle type error from int to ulong and ulong to int --- .../Scened/LoadUnloadDatas/SceneLoadData.cs | 16 +++--- .../Scened/LoadUnloadDatas/SceneUnloadData.cs | 6 +- .../Managing/Scened/SceneLookupData.cs | 26 ++++----- .../Runtime/Managing/Scened/SceneManager.cs | 56 +++++++++---------- .../Runtime/Managing/Scened/UnloadedScene.cs | 8 +-- .../Runtime/Observing/NetworkObserver.cs | 12 ++-- .../Dependencies/Utilities/Dictionaries.cs | 8 +-- .../Runtime/Serializing/Helping/Comparers.cs | 2 +- .../Runtime/Serializing/SceneComparer.cs | 2 +- 9 files changed, 68 insertions(+), 68 deletions(-) diff --git a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneLoadData.cs b/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneLoadData.cs index 51c8cce4..7fcf33db 100644 --- a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneLoadData.cs +++ b/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneLoadData.cs @@ -1,7 +1,7 @@ -using FishNet.Object; -using FishNet.Serializing.Helping; -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; +using FishNet.Object; +using FishNet.Serializing.Helping; using UnityEngine.SceneManagement; namespace FishNet.Managing.Scened @@ -50,13 +50,13 @@ public SceneLoadData(string sceneName) : this(new string[] { sceneName }, null) /// /// /// Scene to load by handle. - public SceneLoadData(int sceneHandle) : this(new int[] { sceneHandle }, null) { } + public SceneLoadData(ulong sceneHandle) : this(new[] { sceneHandle }, null) { } /// /// /// Scene to load by handle. /// Scene to load by name. - public SceneLoadData(int sceneHandle, string sceneName) : this(new SceneLookupData(sceneHandle, sceneName)) { } + public SceneLoadData(ulong sceneHandle, string sceneName) : this(new SceneLookupData(sceneHandle, sceneName)) { } /// /// @@ -76,7 +76,7 @@ public SceneLoadData(List sceneNames) : this(sceneNames.ToArray(), null) /// /// /// Scenes to load by handle. - public SceneLoadData(List sceneHandles) : this(sceneHandles.ToArray(), null) { } + public SceneLoadData(List sceneHandles) : this(sceneHandles.ToArray(), null) { } /// /// @@ -91,7 +91,7 @@ public SceneLoadData(string[] sceneNames) : this(sceneNames, null) { } /// /// /// Scenes to load by handle. - public SceneLoadData(int[] sceneHandles) : this(sceneHandles, null) { } + public SceneLoadData(ulong[] sceneHandles) : this(sceneHandles, null) { } /// /// @@ -132,7 +132,7 @@ public SceneLoadData(string[] sceneNames, NetworkObject[] movedNetworkObjects) /// /// Scenes to load by handle. /// NetworkObjects to move to the first specified scene. - public SceneLoadData(int[] sceneHandles, NetworkObject[] movedNetworkObjects) + public SceneLoadData(ulong[] sceneHandles, NetworkObject[] movedNetworkObjects) { SceneLookupData[] datas = SceneLookupData.CreateData(sceneHandles); Construct(datas, movedNetworkObjects); diff --git a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneUnloadData.cs b/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneUnloadData.cs index 3e577dac..99641049 100644 --- a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneUnloadData.cs +++ b/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneUnloadData.cs @@ -42,7 +42,7 @@ public SceneUnloadData(string sceneName) : this(new string[] { sceneName }) { } /// /// /// Scene to unload by handle. - public SceneUnloadData(int sceneHandle) : this(new int[] { sceneHandle }) { } + public SceneUnloadData(ulong sceneHandle) : this(new[] { sceneHandle }) { } /// /// @@ -65,7 +65,7 @@ public SceneUnloadData(List sceneNames) : this(sceneNames.ToArray()) { } /// /// /// Scenes to unload by handles. - public SceneUnloadData(List sceneHandles) : this(sceneHandles.ToArray()) { } + public SceneUnloadData(List sceneHandles) : this(sceneHandles.ToArray()) { } /// /// @@ -86,7 +86,7 @@ public SceneUnloadData(string[] sceneNames) /// /// /// Scenes to unload by handles. - public SceneUnloadData(int[] sceneHandles) + public SceneUnloadData(ulong[] sceneHandles) { SceneLookupDatas = SceneLookupData.CreateData(sceneHandles); } diff --git a/Assets/FishNet/Runtime/Managing/Scened/SceneLookupData.cs b/Assets/FishNet/Runtime/Managing/Scened/SceneLookupData.cs index 6e3a4554..0f790589 100644 --- a/Assets/FishNet/Runtime/Managing/Scened/SceneLookupData.cs +++ b/Assets/FishNet/Runtime/Managing/Scened/SceneLookupData.cs @@ -1,6 +1,6 @@ -using GameKit.Dependencies.Utilities; -using System; +using System; using System.Collections.Generic; +using GameKit.Dependencies.Utilities; using UnityEngine.SceneManagement; namespace FishNet.Managing.Scened @@ -24,7 +24,7 @@ public static string[] GetNames(this SceneLookupData[] datas) return names; } - + /// /// Returns Names from SceneLookupData. /// @@ -48,7 +48,7 @@ public class SceneLookupData : IEquatable /// /// Handle of the scene. If value is 0, then handle is not used. /// - public int Handle; + public ulong Handle; /// /// Name of the scene. /// @@ -62,7 +62,7 @@ public string NameOnly { if (string.IsNullOrEmpty(Name)) return string.Empty; - + string name = System.IO.Path.GetFileName(Name); return RemoveUnityExtension(name); } @@ -89,7 +89,7 @@ public SceneLookupData() { } /// Scene to generate from. public SceneLookupData(Scene scene) { - Handle = scene.handle; + Handle = scene.handle.GetRawData(); Name = scene.name; } @@ -104,7 +104,7 @@ public SceneLookupData(string name) /// /// /// Scene handle to generate from. - public SceneLookupData(int handle) + public SceneLookupData(ulong handle) { Handle = handle; } @@ -113,7 +113,7 @@ public SceneLookupData(int handle) /// /// Scene handle to generate from. /// Name to generate from if handle is 0. - public SceneLookupData(int handle, string name) + public SceneLookupData(ulong handle, string name) { Handle = handle; Name = name; @@ -212,7 +212,7 @@ public override string ToString() /// /// Scene handle to create from. /// - public static SceneLookupData CreateData(int handle) => new(handle); + public static SceneLookupData CreateData(ulong handle) => new(handle); /// /// Returns a SceneLookupData collection. @@ -233,7 +233,7 @@ public override string ToString() /// /// Scene handles to create from. /// - public static SceneLookupData[] CreateData(List handles) => CreateData(handles.ToArray()); + public static SceneLookupData[] CreateData(List handles) => CreateData(handles.ToArray()); /// /// Returns a SceneLookupData collection. @@ -345,11 +345,11 @@ public static SceneLookupData[] ValidateData(SceneLookupData[] datas) /// /// Scene handles to create from. /// - public static SceneLookupData[] CreateData(int[] handles) + public static SceneLookupData[] CreateData(ulong[] handles) { bool invalidFound = false; List result = new(); - foreach (int item in handles) + foreach (var item in handles) { if (item == 0) { @@ -402,7 +402,7 @@ public Scene GetScene(out bool foundByHandle, bool warnIfDuplicates = true) if (Handle != 0) { result = SceneManager.GetScene(Handle); - if (result.handle != 0) + if (result.handle.GetRawData() != 0) foundByHandle = true; } diff --git a/Assets/FishNet/Runtime/Managing/Scened/SceneManager.cs b/Assets/FishNet/Runtime/Managing/Scened/SceneManager.cs index 6bae7b5c..347cbbcc 100644 --- a/Assets/FishNet/Runtime/Managing/Scened/SceneManager.cs +++ b/Assets/FishNet/Runtime/Managing/Scened/SceneManager.cs @@ -1,4 +1,8 @@ -using FishNet.Connection; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using FishNet.Connection; using FishNet.Managing.Client; using FishNet.Managing.Logging; using FishNet.Managing.Server; @@ -7,10 +11,6 @@ using FishNet.Transporting; using GameKit.Dependencies.Utilities; using GameKit.Dependencies.Utilities.Types; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.Serialization; @@ -34,11 +34,11 @@ public class PendingClientSceneLoads /// /// Scene handles which have clients that have not yet confirmed the loading status. /// - private Dictionary> _scenesWithPendingLoads = new(); + private Dictionary> _scenesWithPendingLoads = new(); /// /// Clients with pending loads, and each scene handle pending. /// - private Dictionary> _clientsWithPendingLoads = new(); + private Dictionary> _clientsWithPendingLoads = new(); /// /// Clients which have been sent the initial scene load with no scenes specified. /// @@ -49,11 +49,11 @@ public class PendingClientSceneLoads /// /// Adds a pending load for a client. /// - public void AddClientToScene(NetworkConnection connection, int sceneHandle) + public void AddClientToScene(NetworkConnection connection, ulong sceneHandle) { /* The client has 1 or more pending loads already. See * if the specified scene is already pending. */ - if (_clientsWithPendingLoads.TryGetValueIL2CPP(connection, out List sceneList)) + if (_clientsWithPendingLoads.TryGetValueIL2CPP(connection, out List sceneList)) { //Scene is already marked for the connection. if (sceneList.Contains(sceneHandle)) @@ -81,14 +81,14 @@ public void AddClientToScene(NetworkConnection connection, int sceneHandle) /// Removes a client from all pending loads. /// Scene handles which no longer have clients pending loads. - internal List RemoveClientFromAllScenes(NetworkConnection conn) + internal List RemoveClientFromAllScenes(NetworkConnection conn) { - List emptyScenes = new(); + List emptyScenes = new(); - if (!_clientsWithPendingLoads.TryGetValueIL2CPP(conn, out List sceneList)) + if (!_clientsWithPendingLoads.TryGetValueIL2CPP(conn, out List sceneList)) return emptyScenes; - foreach (int sceneHandle in sceneList) + foreach (var sceneHandle in sceneList) { /* If the scene is in the clients list then it should * be in scenesWithPendingLoads. This is a safety check but @@ -113,7 +113,7 @@ internal List RemoveClientFromAllScenes(NetworkConnection conn) /// Becomes true if the scene which the connection is being removed from has no more pending loads. /// True if the client had the specified scene as pending. - internal bool RemoveClientFromScene(NetworkConnection conn, int sceneHandle, out bool sceneHasNoPendingLoads) + internal bool RemoveClientFromScene(NetworkConnection conn, ulong sceneHandle, out bool sceneHasNoPendingLoads) { // The scene has does not have any pending clients. if (!_scenesWithPendingLoads.TryGetValueIL2CPP(sceneHandle, out HashSet connectionsLoadingScene)) @@ -136,7 +136,7 @@ internal bool RemoveClientFromScene(NetworkConnection conn, int sceneHandle, out /* If client does not have any pending loads then * there is nothing to remove, which means the requested * scene still has clients in it. */ - if (!_clientsWithPendingLoads.TryGetValueIL2CPP(conn, out List sceneList)) + if (!_clientsWithPendingLoads.TryGetValueIL2CPP(conn, out List sceneList)) { sceneHasNoPendingLoads = false; return false; @@ -176,7 +176,7 @@ internal bool RemoveClientFromScene(NetworkConnection conn, int sceneHandle, out /// /// Returns if a scene has any number of clients still pending load. /// - internal bool HasSceneAnyPendingLoads(int sceneHandle) => _scenesWithPendingLoads.TryGetValueIL2CPP(sceneHandle, out _); + internal bool HasSceneAnyPendingLoads(ulong sceneHandle) => _scenesWithPendingLoads.TryGetValueIL2CPP(sceneHandle, out _); /// /// Clears all information. @@ -635,7 +635,7 @@ private void ClientDisconnected(NetworkConnection conn) /* True if SceneConnections has no more connections * in its scene, as well if the scene checked is in * has no other clients pending load confirmation. */ - bool isSceneNowEmpty = removed && hs.Count == 0 && !_pendingClientSceneLoads.HasSceneAnyPendingLoads(scene.handle); + bool isSceneNowEmpty = removed && hs.Count == 0 && !_pendingClientSceneLoads.HasSceneAnyPendingLoads(scene.handle.GetRawData()); //True if not a global scene and not in scenes to be manually unloaded. bool notGlobalAndNotManualUnload = !IsGlobalScene(scene) && !_manualUnloadScenes.Contains(scene); @@ -1058,7 +1058,7 @@ private IEnumerator __LoadScenes() /* Scene queue data scenes. * All scenes in the scene queue data whether they will be loaded or not. */ List requestedLoadSceneNames = new(); - List requestedLoadSceneHandles = new(); + List requestedLoadSceneHandles = new(); /* Make a null filled array. This will be populated * using loaded scenes, or already loaded (eg cannot be loaded) scenes. */ @@ -1081,7 +1081,7 @@ private IEnumerator __LoadScenes() { requestedLoadSceneNames.Add(s.name); if (byHandle) - requestedLoadSceneHandles.Add(s.handle); + requestedLoadSceneHandles.Add(s.handle.GetRawData()); } if (CanLoadScene(data, lookupData)) @@ -1124,7 +1124,7 @@ private IEnumerator __LoadScenes() } // Connection scenes handles prior to ConnectionScenes being modified. - List connectionScenesHandlesCached = new(); + List connectionScenesHandlesCached = new(); // If replacing scenes. if (replaceScenes != ReplaceOption.None) { @@ -1137,7 +1137,7 @@ private IEnumerator __LoadScenes() { Scene[] sceneConnectionsKeys = SceneConnections.Keys.ToArray(); for (int i = 0; i < sceneConnectionsKeys.Length; i++) - connectionScenesHandlesCached.Add(sceneConnectionsKeys[i].handle); + connectionScenesHandlesCached.Add(sceneConnectionsKeys[i].handle.GetRawData()); // If global then remove all connections from all scenes. if (data.ScopeType == SceneScopeType.Global) @@ -1155,7 +1155,7 @@ private IEnumerator __LoadScenes() else { foreach (Scene s in NetworkManager.ClientManager.Connection.Scenes) - connectionScenesHandlesCached.Add(s.handle); + connectionScenesHandlesCached.Add(s.handle.GetRawData()); } } @@ -1181,7 +1181,7 @@ private IEnumerator __LoadScenes() if (requestedLoadSceneNames.Contains(s.name)) continue; // Same as above but using handles. - if (requestedLoadSceneHandles.Contains(s.handle)) + if (requestedLoadSceneHandles.Contains(s.handle.GetRawData())) continue; /* Cannot unload global scenes. If * replace scenes was used for a global @@ -1193,7 +1193,7 @@ private IEnumerator __LoadScenes() if (_manualUnloadScenes.Contains(s)) continue; - bool inScenesCache = connectionScenesHandlesCached.Contains(s.handle); + bool inScenesCache = connectionScenesHandlesCached.Contains(s.handle.GetRawData()); HashSet conns; bool inScenesCurrent = SceneConnections.ContainsKey(s); // If was in scenes previously but isnt now then no connections reside in the scene. @@ -2245,13 +2245,13 @@ public static Scene GetScene(string sceneName, NetworkManager nm = null, bool wa /// /// /// - public static Scene GetScene(int sceneHandle) + public static Scene GetScene(ulong sceneHandle) { int count = UnitySceneManager.sceneCount; for (int i = 0; i < count; i++) { Scene s = UnitySceneManager.GetSceneAt(i); - if (s.handle == sceneHandle) + if (s.handle.GetRawData() == sceneHandle) return s; } @@ -2354,7 +2354,7 @@ private void RemoveOccupiedScenes(List scenes) { Scene s = scenes[i]; - if (SceneConnections.TryGetValueIL2CPP(s, out _) || _pendingClientSceneLoads.HasSceneAnyPendingLoads(s.handle)) + if (SceneConnections.TryGetValueIL2CPP(s, out _) || _pendingClientSceneLoads.HasSceneAnyPendingLoads(s.handle.GetRawData())) { scenes.RemoveAt(i); i--; @@ -2365,7 +2365,7 @@ private void RemoveOccupiedScenes(List scenes) /// /// Adds a pending load for a connection. /// - private void AddPendingLoad(NetworkConnection[] conns, int sceneHandle) + private void AddPendingLoad(NetworkConnection[] conns, ulong sceneHandle) { foreach (NetworkConnection c in conns) { diff --git a/Assets/FishNet/Runtime/Managing/Scened/UnloadedScene.cs b/Assets/FishNet/Runtime/Managing/Scened/UnloadedScene.cs index 5f89fb49..2897a751 100644 --- a/Assets/FishNet/Runtime/Managing/Scened/UnloadedScene.cs +++ b/Assets/FishNet/Runtime/Managing/Scened/UnloadedScene.cs @@ -5,15 +5,15 @@ namespace FishNet.Managing.Scened public struct UnloadedScene { public readonly string Name; - public readonly int Handle; + public readonly ulong Handle; public UnloadedScene(Scene s) { Name = s.name; - Handle = s.handle; + Handle = s.handle.GetRawData(); } - public UnloadedScene(string name, int handle) + public UnloadedScene(string name, ulong handle) { Name = name; Handle = handle; @@ -30,7 +30,7 @@ public Scene GetScene() for (int i = 0; i < loadedScenes; i++) { Scene s = UnityEngine.SceneManagement.SceneManager.GetSceneAt(i); - if (s.IsValid() && s.handle == Handle) + if (s.IsValid() && s.handle.GetRawData() == Handle) return s; } diff --git a/Assets/FishNet/Runtime/Observing/NetworkObserver.cs b/Assets/FishNet/Runtime/Observing/NetworkObserver.cs index fd0fb35d..073a2e41 100644 --- a/Assets/FishNet/Runtime/Observing/NetworkObserver.cs +++ b/Assets/FishNet/Runtime/Observing/NetworkObserver.cs @@ -1,11 +1,11 @@ -using FishNet.Connection; +using System.Collections.Generic; +using FishNet.Connection; using FishNet.Documenting; +using FishNet.Managing; using FishNet.Managing.Server; using FishNet.Object; using FishNet.Transporting; using GameKit.Dependencies.Utilities; -using System.Collections.Generic; -using FishNet.Managing; using UnityEngine; namespace FishNet.Observing @@ -158,7 +158,7 @@ internal void Deinitialize(bool destroyed) /* Use GetInstanceId to ensure the object is actually * instantiated. If Id is negative, then it's instantiated * and not a reference to the original object. */ - if (destroyed && item.GetInstanceID() < 0) + if (destroyed && item.GetEntityId().IsValid()) Destroy(item); } @@ -309,10 +309,10 @@ internal ObserverStateChange RebuildObservers(NetworkConnection connection, bool if (!_initialized) { string goName = gameObject == null ? "Empty" : gameObject.name; - + NetworkManager nm = _networkObject == null ? null : _networkObject.NetworkManager; nm.LogError($"{GetType().Name} is not initialized on NetworkObject [{goName}]. RebuildObservers should not be called. If you are able to reproduce this error consistently please report this issue."); - + return ObserverStateChange.Unchanged; } diff --git a/Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Dictionaries.cs b/Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Dictionaries.cs index cd5c03ca..2678c26e 100644 --- a/Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Dictionaries.cs +++ b/Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Dictionaries.cs @@ -11,7 +11,7 @@ public static class DictionaryFN /// public static bool TryGetValueIL2CPP(this IReadOnlyDictionary dict, TKey key, out TValue value) { - #if ENABLE_IL2CPP && UNITY_IOS || UNITY_ANDROID +#if ENABLE_IL2CPP && UNITY_IOS || UNITY_ANDROID if (dict.ContainsKey(key)) { value = dict[key]; @@ -20,12 +20,12 @@ public static bool TryGetValueIL2CPP(this IReadOnlyDictionary /// Returns values as a list. /// diff --git a/Assets/FishNet/Runtime/Serializing/Helping/Comparers.cs b/Assets/FishNet/Runtime/Serializing/Helping/Comparers.cs index f294ae66..b532bc3c 100644 --- a/Assets/FishNet/Runtime/Serializing/Helping/Comparers.cs +++ b/Assets/FishNet/Runtime/Serializing/Helping/Comparers.cs @@ -48,7 +48,7 @@ public bool Equals(Scene a, Scene b) if (!a.IsValid() || !b.IsValid()) return false; - if (a.handle != 0 || b.handle != 0) + if (a.handle.GetRawData() != 0 || b.handle.GetRawData() != 0) return a.handle == b.handle; return a.name == b.name; diff --git a/Assets/FishNet/Runtime/Serializing/SceneComparer.cs b/Assets/FishNet/Runtime/Serializing/SceneComparer.cs index d4a4e076..9181469a 100644 --- a/Assets/FishNet/Runtime/Serializing/SceneComparer.cs +++ b/Assets/FishNet/Runtime/Serializing/SceneComparer.cs @@ -12,7 +12,7 @@ public override bool Equals(Scene a, Scene b) public override int GetHashCode(Scene obj) { - return obj.handle; + return obj.handle.GetHashCode(); } } } \ No newline at end of file From a259cdc4a45add8b4701f221fc024a1c91bdce5a Mon Sep 17 00:00:00 2001 From: JulianMKhoo Date: Thu, 25 Jun 2026 11:52:04 +0700 Subject: [PATCH 2/3] fix: old unity version can work properly and scene id lower than zero comparison --- .../Managing/Scened/SceneHandleExtensions.cs | 23 +++++++++++++++++++ .../Managing/Scened/SceneLookupData.cs | 4 ++-- .../Runtime/Managing/Scened/SceneManager.cs | 16 ++++++------- .../Runtime/Managing/Scened/UnloadedScene.cs | 4 ++-- .../Runtime/Observing/NetworkObserver.cs | 2 +- .../Runtime/Serializing/Helping/Comparers.cs | 3 ++- 6 files changed, 38 insertions(+), 14 deletions(-) create mode 100644 Assets/FishNet/Runtime/Managing/Scened/SceneHandleExtensions.cs diff --git a/Assets/FishNet/Runtime/Managing/Scened/SceneHandleExtensions.cs b/Assets/FishNet/Runtime/Managing/Scened/SceneHandleExtensions.cs new file mode 100644 index 00000000..e0e2f437 --- /dev/null +++ b/Assets/FishNet/Runtime/Managing/Scened/SceneHandleExtensions.cs @@ -0,0 +1,23 @@ +using UnityEngine.SceneManagement; + +namespace FishNet.Managing.Scened +{ + internal static class SceneHandleExtensions + { + /// + /// Returns the raw handle identifier of a scene as a ulong. + /// + /// + /// Unity 6000.5+ changed Scene.handle to an EntityId struct exposing GetRawData(). + /// Earlier versions expose handle as an int. + /// + public static ulong GetHandleId(this Scene s) + { +#if UNITY_6000_5_OR_NEWER + return s.handle.GetRawData(); +#else + return (ulong)(uint)s.handle; +#endif + } + } +} diff --git a/Assets/FishNet/Runtime/Managing/Scened/SceneLookupData.cs b/Assets/FishNet/Runtime/Managing/Scened/SceneLookupData.cs index 0f790589..6e65d686 100644 --- a/Assets/FishNet/Runtime/Managing/Scened/SceneLookupData.cs +++ b/Assets/FishNet/Runtime/Managing/Scened/SceneLookupData.cs @@ -89,7 +89,7 @@ public SceneLookupData() { } /// Scene to generate from. public SceneLookupData(Scene scene) { - Handle = scene.handle.GetRawData(); + Handle = scene.GetHandleId(); Name = scene.name; } @@ -402,7 +402,7 @@ public Scene GetScene(out bool foundByHandle, bool warnIfDuplicates = true) if (Handle != 0) { result = SceneManager.GetScene(Handle); - if (result.handle.GetRawData() != 0) + if (result.GetHandleId() != 0) foundByHandle = true; } diff --git a/Assets/FishNet/Runtime/Managing/Scened/SceneManager.cs b/Assets/FishNet/Runtime/Managing/Scened/SceneManager.cs index 347cbbcc..165e02d9 100644 --- a/Assets/FishNet/Runtime/Managing/Scened/SceneManager.cs +++ b/Assets/FishNet/Runtime/Managing/Scened/SceneManager.cs @@ -635,7 +635,7 @@ private void ClientDisconnected(NetworkConnection conn) /* True if SceneConnections has no more connections * in its scene, as well if the scene checked is in * has no other clients pending load confirmation. */ - bool isSceneNowEmpty = removed && hs.Count == 0 && !_pendingClientSceneLoads.HasSceneAnyPendingLoads(scene.handle.GetRawData()); + bool isSceneNowEmpty = removed && hs.Count == 0 && !_pendingClientSceneLoads.HasSceneAnyPendingLoads(scene.GetHandleId()); //True if not a global scene and not in scenes to be manually unloaded. bool notGlobalAndNotManualUnload = !IsGlobalScene(scene) && !_manualUnloadScenes.Contains(scene); @@ -1081,7 +1081,7 @@ private IEnumerator __LoadScenes() { requestedLoadSceneNames.Add(s.name); if (byHandle) - requestedLoadSceneHandles.Add(s.handle.GetRawData()); + requestedLoadSceneHandles.Add(s.GetHandleId()); } if (CanLoadScene(data, lookupData)) @@ -1137,7 +1137,7 @@ private IEnumerator __LoadScenes() { Scene[] sceneConnectionsKeys = SceneConnections.Keys.ToArray(); for (int i = 0; i < sceneConnectionsKeys.Length; i++) - connectionScenesHandlesCached.Add(sceneConnectionsKeys[i].handle.GetRawData()); + connectionScenesHandlesCached.Add(sceneConnectionsKeys[i].GetHandleId()); // If global then remove all connections from all scenes. if (data.ScopeType == SceneScopeType.Global) @@ -1155,7 +1155,7 @@ private IEnumerator __LoadScenes() else { foreach (Scene s in NetworkManager.ClientManager.Connection.Scenes) - connectionScenesHandlesCached.Add(s.handle.GetRawData()); + connectionScenesHandlesCached.Add(s.GetHandleId()); } } @@ -1181,7 +1181,7 @@ private IEnumerator __LoadScenes() if (requestedLoadSceneNames.Contains(s.name)) continue; // Same as above but using handles. - if (requestedLoadSceneHandles.Contains(s.handle.GetRawData())) + if (requestedLoadSceneHandles.Contains(s.GetHandleId())) continue; /* Cannot unload global scenes. If * replace scenes was used for a global @@ -1193,7 +1193,7 @@ private IEnumerator __LoadScenes() if (_manualUnloadScenes.Contains(s)) continue; - bool inScenesCache = connectionScenesHandlesCached.Contains(s.handle.GetRawData()); + bool inScenesCache = connectionScenesHandlesCached.Contains(s.GetHandleId()); HashSet conns; bool inScenesCurrent = SceneConnections.ContainsKey(s); // If was in scenes previously but isnt now then no connections reside in the scene. @@ -2251,7 +2251,7 @@ public static Scene GetScene(ulong sceneHandle) for (int i = 0; i < count; i++) { Scene s = UnitySceneManager.GetSceneAt(i); - if (s.handle.GetRawData() == sceneHandle) + if (s.GetHandleId() == sceneHandle) return s; } @@ -2354,7 +2354,7 @@ private void RemoveOccupiedScenes(List scenes) { Scene s = scenes[i]; - if (SceneConnections.TryGetValueIL2CPP(s, out _) || _pendingClientSceneLoads.HasSceneAnyPendingLoads(s.handle.GetRawData())) + if (SceneConnections.TryGetValueIL2CPP(s, out _) || _pendingClientSceneLoads.HasSceneAnyPendingLoads(s.GetHandleId())) { scenes.RemoveAt(i); i--; diff --git a/Assets/FishNet/Runtime/Managing/Scened/UnloadedScene.cs b/Assets/FishNet/Runtime/Managing/Scened/UnloadedScene.cs index 2897a751..6e21c8c6 100644 --- a/Assets/FishNet/Runtime/Managing/Scened/UnloadedScene.cs +++ b/Assets/FishNet/Runtime/Managing/Scened/UnloadedScene.cs @@ -10,7 +10,7 @@ public struct UnloadedScene public UnloadedScene(Scene s) { Name = s.name; - Handle = s.handle.GetRawData(); + Handle = s.GetHandleId(); } public UnloadedScene(string name, ulong handle) @@ -30,7 +30,7 @@ public Scene GetScene() for (int i = 0; i < loadedScenes; i++) { Scene s = UnityEngine.SceneManagement.SceneManager.GetSceneAt(i); - if (s.IsValid() && s.handle.GetRawData() == Handle) + if (s.IsValid() && s.GetHandleId() == Handle) return s; } diff --git a/Assets/FishNet/Runtime/Observing/NetworkObserver.cs b/Assets/FishNet/Runtime/Observing/NetworkObserver.cs index 073a2e41..f148dc75 100644 --- a/Assets/FishNet/Runtime/Observing/NetworkObserver.cs +++ b/Assets/FishNet/Runtime/Observing/NetworkObserver.cs @@ -158,7 +158,7 @@ internal void Deinitialize(bool destroyed) /* Use GetInstanceId to ensure the object is actually * instantiated. If Id is negative, then it's instantiated * and not a reference to the original object. */ - if (destroyed && item.GetEntityId().IsValid()) + if (destroyed && item.GetInstanceID() < 0) Destroy(item); } diff --git a/Assets/FishNet/Runtime/Serializing/Helping/Comparers.cs b/Assets/FishNet/Runtime/Serializing/Helping/Comparers.cs index b532bc3c..98cb2ac5 100644 --- a/Assets/FishNet/Runtime/Serializing/Helping/Comparers.cs +++ b/Assets/FishNet/Runtime/Serializing/Helping/Comparers.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using FishNet.Managing.Scened; using UnityEngine.SceneManagement; namespace FishNet.Serializing.Helping @@ -48,7 +49,7 @@ public bool Equals(Scene a, Scene b) if (!a.IsValid() || !b.IsValid()) return false; - if (a.handle.GetRawData() != 0 || b.handle.GetRawData() != 0) + if (a.GetHandleId() != 0 || b.GetHandleId() != 0) return a.handle == b.handle; return a.name == b.name; From 88c6b03ba6657d949fe6ed3640191b69cb910373 Mon Sep 17 00:00:00 2001 From: JulianMKhoo Date: Thu, 25 Jun 2026 12:15:35 +0700 Subject: [PATCH 3/3] fix: network destroy item correctly --- Assets/FishNet/Runtime/Observing/NetworkObserver.cs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Assets/FishNet/Runtime/Observing/NetworkObserver.cs b/Assets/FishNet/Runtime/Observing/NetworkObserver.cs index f148dc75..7b80f7fc 100644 --- a/Assets/FishNet/Runtime/Observing/NetworkObserver.cs +++ b/Assets/FishNet/Runtime/Observing/NetworkObserver.cs @@ -155,11 +155,18 @@ internal void Deinitialize(bool destroyed) foreach (ObserverCondition item in _observerConditions) { item.Deinitialize(destroyed); - /* Use GetInstanceId to ensure the object is actually - * instantiated. If Id is negative, then it's instantiated - * and not a reference to the original object. */ + /* Conditions are always Instantiate() clones at this point + * (see Initialize), so destroying any valid entry only ever + * destroys the clone, never the source asset. + * On 6000.5+ use the EntityId API: GetInstanceID()/`< 0` + * route through the obsolete EntityId<->int conversion (CS0618). */ +#if UNITY_6000_5_OR_NEWER + if (destroyed && item.GetEntityId().IsValid()) + Destroy(item); +#else if (destroyed && item.GetInstanceID() < 0) Destroy(item); +#endif } // Clean up lists.