diff --git a/Assets/FishNet/Runtime/Managing/Scened/SceneLookupData.cs b/Assets/FishNet/Runtime/Managing/Scened/SceneLookupData.cs
index 6e3a4554..a84ec970 100644
--- a/Assets/FishNet/Runtime/Managing/Scened/SceneLookupData.cs
+++ b/Assets/FishNet/Runtime/Managing/Scened/SceneLookupData.cs
@@ -1,4 +1,5 @@
-using GameKit.Dependencies.Utilities;
+using FishNet.Utility;
+using GameKit.Dependencies.Utilities;
using System;
using System.Collections.Generic;
using UnityEngine.SceneManagement;
@@ -24,7 +25,6 @@ public static string[] GetNames(this SceneLookupData[] datas)
return names;
}
-
///
/// Returns Names from SceneLookupData.
///
@@ -46,13 +46,33 @@ public static string[] GetNamesOnly(this SceneLookupData[] datas)
public class SceneLookupData : IEquatable
{
///
- /// Handle of the scene. If value is 0, then handle is not used.
+ /// Raw handle of the scene. If value is 0, then handle is not used.
///
- public int Handle;
+ private ulong _rawHandle;
+
+ ///
+ /// Legacy 32-bit handle view.
+ ///
+ public int Handle
+ {
+ get => unchecked((int)_rawHandle);
+ set => _rawHandle = unchecked((uint)value);
+ }
+
+ ///
+ /// Raw scene handle value.
+ ///
+ public ulong RawHandle
+ {
+ get => _rawHandle;
+ set => _rawHandle = value;
+ }
+
///
/// Name of the scene.
///
public string Name = string.Empty;
+
///
/// Returns the scene name without a directory path should one exist.
///
@@ -62,16 +82,17 @@ public string NameOnly
{
if (string.IsNullOrEmpty(Name))
return string.Empty;
-
+
string name = System.IO.Path.GetFileName(Name);
return RemoveUnityExtension(name);
}
}
+
///
/// Returns if this data is valid for use.
/// Being valid does not mean that the scene exist, rather that there is enough data to try and lookup a scene.
///
- public bool IsValid => Name != string.Empty || Handle != 0;
+ public bool IsValid => Name != string.Empty || RawHandle != 0;
#region Const
///
@@ -89,7 +110,7 @@ public SceneLookupData() { }
/// Scene to generate from.
public SceneLookupData(Scene scene)
{
- Handle = scene.handle;
+ RawHandle = UnityCompatibility.GetSceneHandleRaw(scene);
Name = scene.name;
}
@@ -109,6 +130,14 @@ public SceneLookupData(int handle)
Handle = handle;
}
+ ///
+ ///
+ /// Raw scene handle to generate from.
+ public SceneLookupData(ulong handle)
+ {
+ RawHandle = handle;
+ }
+
///
///
/// Scene handle to generate from.
@@ -119,6 +148,16 @@ public SceneLookupData(int handle, string name)
Name = name;
}
+ ///
+ ///
+ /// Raw scene handle to generate from.
+ /// Name to generate from if handle is 0.
+ public SceneLookupData(ulong handle, string name)
+ {
+ RawHandle = handle;
+ Name = name;
+ }
+
#region Comparers.
public static bool operator ==(SceneLookupData sldA, SceneLookupData sldB)
{
@@ -159,10 +198,10 @@ public bool Equals(SceneLookupData sld)
return false;
// True if both handles are empty.
- bool bothHandlesEmpty = Handle == 0 && sld.Handle == 0;
+ bool bothHandlesEmpty = RawHandle == 0 && sld.RawHandle == 0;
// If both have handles and they match.
- if (!bothHandlesEmpty && sld.Handle == Handle)
+ if (!bothHandlesEmpty && sld.RawHandle == RawHandle)
return true;
// If neither have handles and name matches.
else if (bothHandlesEmpty && sld.Name == Name)
@@ -175,7 +214,7 @@ public bool Equals(SceneLookupData sld)
public override int GetHashCode()
{
int hashCode = 2053068273;
- hashCode = hashCode * -1521134295 + Handle.GetHashCode();
+ hashCode = hashCode * -1521134295 + RawHandle.GetHashCode();
hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(Name);
return hashCode;
}
@@ -187,7 +226,7 @@ public override bool Equals(object obj)
public override string ToString()
{
- return $"Name {Name}, Handle {Handle}";
+ return $"Name {Name}, Handle {RawHandle}";
// return base.ToString();
}
#endregion
@@ -214,6 +253,13 @@ public override string ToString()
///
public static SceneLookupData CreateData(int handle) => new(handle);
+ ///
+ /// Returns a new SceneLookupData.
+ ///
+ /// Raw scene handle to create from.
+ ///
+ public static SceneLookupData CreateData(ulong handle) => new(handle);
+
///
/// Returns a SceneLookupData collection.
///
@@ -235,6 +281,13 @@ public override string ToString()
///
public static SceneLookupData[] CreateData(List handles) => CreateData(handles.ToArray());
+ ///
+ /// Returns a SceneLookupData collection.
+ ///
+ /// Raw scene handles to create from.
+ ///
+ public static SceneLookupData[] CreateData(List handles) => CreateData(handles.ToArray());
+
///
/// Returns a SceneLookupData collection.
///
@@ -297,12 +350,12 @@ public static SceneLookupData[] ValidateData(SceneLookupData[] datas)
for (int i = 0; i < result.Count; i++)
{
bool nameMatches = result[i].Name == item.Name;
- bool handleMatches = result[i].Handle == item.Handle;
+ bool handleMatches = result[i].RawHandle == item.RawHandle;
// Handle is the same (could be 0 handle).
if (handleMatches)
{
// If handle matches and not default then the same scene was added multiple times.
- if (item.Handle != 0)
+ if (item.RawHandle != 0)
failingIndex = i;
}
// Name is the same.
@@ -365,6 +418,32 @@ public static SceneLookupData[] CreateData(int[] handles)
return result.ToArray();
}
+
+ ///
+ /// Returns a SceneLookupData collection.
+ ///
+ /// Raw scene handles to create from.
+ ///
+ public static SceneLookupData[] CreateData(ulong[] handles)
+ {
+ bool invalidFound = false;
+ List result = new();
+ foreach (ulong item in handles)
+ {
+ if (item == 0)
+ {
+ invalidFound = true;
+ continue;
+ }
+
+ result.Add(CreateData(item));
+ }
+
+ if (invalidFound)
+ NetworkManagerExtensions.LogWarning(INVALID_SCENE);
+
+ return result.ToArray();
+ }
#endregion
///
@@ -390,7 +469,7 @@ public Scene GetScene(out bool foundByHandle, bool warnIfDuplicates = true)
{
foundByHandle = false;
- if (Handle == 0 && string.IsNullOrEmpty(NameOnly))
+ if (RawHandle == 0 && string.IsNullOrEmpty(NameOnly))
{
NetworkManagerExtensions.LogWarning("Scene handle and name is unset; scene cannot be returned.");
return default;
@@ -398,11 +477,11 @@ public Scene GetScene(out bool foundByHandle, bool warnIfDuplicates = true)
Scene result = default;
- // Lookup my handle.
- if (Handle != 0)
+ // Lookup by handle first.
+ if (RawHandle != 0)
{
- result = SceneManager.GetScene(Handle);
- if (result.handle != 0)
+ result = GetSceneByRawHandle(RawHandle);
+ if (UnityCompatibility.HasValidSceneHandle(result))
foundByHandle = true;
}
@@ -412,5 +491,21 @@ public Scene GetScene(out bool foundByHandle, bool warnIfDuplicates = true)
return result;
}
+
+ ///
+ /// Returns a currently loaded scene by raw scene handle.
+ ///
+ private static Scene GetSceneByRawHandle(ulong rawHandle)
+ {
+ int count = UnityEngine.SceneManagement.SceneManager.sceneCount;
+ for (int i = 0; i < count; i++)
+ {
+ Scene scene = UnityEngine.SceneManagement.SceneManager.GetSceneAt(i);
+ if (scene.IsValid() && UnityCompatibility.GetSceneHandleRaw(scene) == rawHandle)
+ return scene;
+ }
+
+ return default;
+ }
}
}
\ No newline at end of file
diff --git a/Assets/FishNet/Runtime/Managing/Scened/SceneManager.cs b/Assets/FishNet/Runtime/Managing/Scened/SceneManager.cs
index 6bae7b5c..d53b8378 100644
--- a/Assets/FishNet/Runtime/Managing/Scened/SceneManager.cs
+++ b/Assets/FishNet/Runtime/Managing/Scened/SceneManager.cs
@@ -5,6 +5,7 @@
using FishNet.Object;
using FishNet.Serializing.Helping;
using FishNet.Transporting;
+using FishNet.Utility;
using GameKit.Dependencies.Utilities;
using GameKit.Dependencies.Utilities.Types;
using System;
@@ -34,11 +35,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 +50,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 +82,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 (ulong 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 +114,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 +137,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 +177,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.
@@ -576,7 +577,7 @@ void SendEmptyBroadcast()
};
foreach (SceneLookupData lookupData in sceneLookupData)
- _pendingClientSceneLoads.AddClientToScene(connection, lookupData.Handle);
+ _pendingClientSceneLoads.AddClientToScene(connection, lookupData.RawHandle);
connection.Broadcast(msg, requireAuthenticated: true);
}
@@ -635,7 +636,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(UnityCompatibility.GetSceneHandleRaw(scene));
//True if not a global scene and not in scenes to be manually unloaded.
bool notGlobalAndNotManualUnload = !IsGlobalScene(scene) && !_manualUnloadScenes.Contains(scene);
@@ -691,9 +692,9 @@ private void OnClientLoadedScenes(NetworkConnection conn, ClientScenesLoadedBroa
foreach (SceneLookupData item in msg.SceneLookupDatas)
{
//Make sure the sceneId is pending.
- if (!_pendingClientSceneLoads.RemoveClientFromScene(conn, item.Handle, out _))
+ if (!_pendingClientSceneLoads.RemoveClientFromScene(conn, item.RawHandle, out _))
{
- KickClient($"Client {conn.ToString()} sent a scene load response for handle [{item.Handle}], but client was not sent a load for this handle.");
+ KickClient($"Client {conn.ToString()} sent a scene load response for handle [{item.RawHandle}], but client was not sent a load for this handle.");
break;
}
@@ -1058,7 +1059,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 +1082,7 @@ private IEnumerator __LoadScenes()
{
requestedLoadSceneNames.Add(s.name);
if (byHandle)
- requestedLoadSceneHandles.Add(s.handle);
+ requestedLoadSceneHandles.Add(UnityCompatibility.GetSceneHandleRaw(s));
}
if (CanLoadScene(data, lookupData))
@@ -1124,7 +1125,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 +1138,7 @@ private IEnumerator __LoadScenes()
{
Scene[] sceneConnectionsKeys = SceneConnections.Keys.ToArray();
for (int i = 0; i < sceneConnectionsKeys.Length; i++)
- connectionScenesHandlesCached.Add(sceneConnectionsKeys[i].handle);
+ connectionScenesHandlesCached.Add(UnityCompatibility.GetSceneHandleRaw(sceneConnectionsKeys[i]));
// If global then remove all connections from all scenes.
if (data.ScopeType == SceneScopeType.Global)
@@ -1155,7 +1156,7 @@ private IEnumerator __LoadScenes()
else
{
foreach (Scene s in NetworkManager.ClientManager.Connection.Scenes)
- connectionScenesHandlesCached.Add(s.handle);
+ connectionScenesHandlesCached.Add(UnityCompatibility.GetSceneHandleRaw(s));
}
}
@@ -1181,7 +1182,7 @@ private IEnumerator __LoadScenes()
if (requestedLoadSceneNames.Contains(s.name))
continue;
// Same as above but using handles.
- if (requestedLoadSceneHandles.Contains(s.handle))
+ if (requestedLoadSceneHandles.Contains(UnityCompatibility.GetSceneHandleRaw(s)))
continue;
/* Cannot unload global scenes. If
* replace scenes was used for a global
@@ -1193,7 +1194,7 @@ private IEnumerator __LoadScenes()
if (_manualUnloadScenes.Contains(s))
continue;
- bool inScenesCache = connectionScenesHandlesCached.Contains(s.handle);
+ bool inScenesCache = connectionScenesHandlesCached.Contains(UnityCompatibility.GetSceneHandleRaw(s));
HashSet conns;
bool inScenesCurrent = SceneConnections.ContainsKey(s);
// If was in scenes previously but isnt now then no connections reside in the scene.
@@ -1328,7 +1329,7 @@ void InvokePercentageChange(int index, float maximumWorth, float currentScenePer
/* If the first lookup data contains a handle and the scene
* is found for that handle then use that as the moved to scene.
* Nobs always move to the first specified scene. */
- if (sceneLoadData.SceneLookupDatas[0].Handle != 0 && !string.IsNullOrEmpty(firstScene.name))
+ if (sceneLoadData.SceneLookupDatas[0].RawHandle != 0 && !string.IsNullOrEmpty(firstScene.name))
{
firstValidScene = firstScene;
}
@@ -1503,7 +1504,7 @@ void AddClientPendingLoads(NetworkConnection[] lConns)
{
SceneLookupData[] slds = msg.QueueData.SceneLoadData.SceneLookupDatas;
foreach (SceneLookupData sld in slds)
- AddPendingLoad(lConns, sld.Handle);
+ AddPendingLoad(lConns, sld.RawHandle);
}
}
/* If running as client then send a message
@@ -2246,12 +2247,22 @@ public static Scene GetScene(string sceneName, NetworkManager nm = null, bool wa
///
///
public static Scene GetScene(int sceneHandle)
+ {
+ return GetScene(unchecked((uint)sceneHandle));
+ }
+
+ ///
+ /// Returns a scene by raw handle.
+ ///
+ ///
+ ///
+ 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 (UnityCompatibility.GetSceneHandleRaw(s) == sceneHandle)
return s;
}
@@ -2354,7 +2365,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(UnityCompatibility.GetSceneHandleRaw(s)))
{
scenes.RemoveAt(i);
i--;
@@ -2365,7 +2376,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..2fcb0dd4 100644
--- a/Assets/FishNet/Runtime/Managing/Scened/UnloadedScene.cs
+++ b/Assets/FishNet/Runtime/Managing/Scened/UnloadedScene.cs
@@ -1,19 +1,26 @@
-using UnityEngine.SceneManagement;
+using FishNet.Utility;
+using UnityEngine.SceneManagement;
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 = UnityCompatibility.GetSceneHandleRaw(s);
}
public UnloadedScene(string name, int handle)
+ {
+ Name = name;
+ Handle = unchecked((uint)handle);
+ }
+
+ public UnloadedScene(string name, ulong handle)
{
Name = name;
Handle = handle;
@@ -30,7 +37,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() && UnityCompatibility.GetSceneHandleRaw(s) == Handle)
return s;
}
diff --git a/Assets/FishNet/Runtime/Observing/NetworkObserver.cs b/Assets/FishNet/Runtime/Observing/NetworkObserver.cs
index fd0fb35d..c9a05a48 100644
--- a/Assets/FishNet/Runtime/Observing/NetworkObserver.cs
+++ b/Assets/FishNet/Runtime/Observing/NetworkObserver.cs
@@ -155,10 +155,12 @@ 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. */
- if (destroyed && item.GetInstanceID() < 0)
+
+ /* Conditions are replaced with instantiated copies during Initialize.
+ * Destroy the runtime copies when this observer is being destroyed.
+ * Do not rely on InstanceID sign because InstanceID is obsolete in Unity 6.5+.
+ */
+ if (destroyed)
Destroy(item);
}
@@ -309,10 +311,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/Serializing/Helping/Comparers.cs b/Assets/FishNet/Runtime/Serializing/Helping/Comparers.cs
index f294ae66..7ab92cbe 100644
--- a/Assets/FishNet/Runtime/Serializing/Helping/Comparers.cs
+++ b/Assets/FishNet/Runtime/Serializing/Helping/Comparers.cs
@@ -1,4 +1,5 @@
-using System;
+using FishNet.Utility;
+using System;
using System.Collections.Generic;
using UnityEngine.SceneManagement;
@@ -10,6 +11,7 @@ public class PublicPropertyComparer
/// Compare if T is default.
///
public static Func IsDefault { get; set; }
+
///
/// Compare if T is the same as T2.
///
@@ -48,8 +50,11 @@ public bool Equals(Scene a, Scene b)
if (!a.IsValid() || !b.IsValid())
return false;
- if (a.handle != 0 || b.handle != 0)
- return a.handle == b.handle;
+ ulong aHandle = UnityCompatibility.GetSceneHandleRaw(a);
+ ulong bHandle = UnityCompatibility.GetSceneHandleRaw(b);
+
+ if (aHandle != 0 || bHandle != 0)
+ return aHandle == bHandle;
return a.name == b.name;
}
diff --git a/Assets/FishNet/Runtime/Serializing/SceneComparer.cs b/Assets/FishNet/Runtime/Serializing/SceneComparer.cs
index d4a4e076..d09b802f 100644
--- a/Assets/FishNet/Runtime/Serializing/SceneComparer.cs
+++ b/Assets/FishNet/Runtime/Serializing/SceneComparer.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using FishNet.Utility;
+using System.Collections.Generic;
using UnityEngine.SceneManagement;
namespace FishNet.Serializing.Helping
@@ -7,12 +8,12 @@ internal sealed class SceneHandleEqualityComparer : EqualityComparer
{
public override bool Equals(Scene a, Scene b)
{
- return a.handle == b.handle;
+ return UnityCompatibility.GetSceneHandleRaw(a) == UnityCompatibility.GetSceneHandleRaw(b);
}
public override int GetHashCode(Scene obj)
{
- return obj.handle;
+ return UnityCompatibility.GetSceneHandleRaw(obj).GetHashCode();
}
}
}
\ No newline at end of file
diff --git a/Assets/FishNet/Runtime/UnityCompatibility.cs b/Assets/FishNet/Runtime/UnityCompatibility.cs
new file mode 100644
index 00000000..81f26979
--- /dev/null
+++ b/Assets/FishNet/Runtime/UnityCompatibility.cs
@@ -0,0 +1,54 @@
+using UnityEngine.SceneManagement;
+
+namespace FishNet.Utility
+{
+ ///
+ /// Compatibility helpers for Unity API changes across supported Unity versions.
+ ///
+ public static class UnityCompatibility
+ {
+ ///
+ /// Returns a runtime object identifier using Unity's current object identity API.
+ ///
+ public static ulong GetObjectRuntimeId(UnityEngine.Object obj)
+ {
+#if UNITY_6000_5_OR_NEWER
+ return obj.GetEntityId().GetRawData();
+#else
+ return unchecked((uint)obj.GetInstanceID());
+#endif
+ }
+
+ ///
+ /// Returns a raw scene handle value using Unity's current SceneHandle API.
+ ///
+ public static ulong GetSceneHandleRaw(Scene scene)
+ {
+#if UNITY_6000_5_OR_NEWER
+ return scene.handle.GetRawData();
+#else
+ return unchecked((uint)(int)scene.handle);
+#endif
+ }
+
+ ///
+ /// Creates a SceneHandle from raw scene handle data.
+ ///
+ public static SceneHandle SceneHandleFromRaw(ulong rawHandle)
+ {
+#if UNITY_6000_5_OR_NEWER
+ return SceneHandle.FromRawData(rawHandle);
+#else
+ return (SceneHandle)(int)rawHandle;
+#endif
+ }
+
+ ///
+ /// Returns true if the scene has a non-zero raw handle.
+ ///
+ public static bool HasValidSceneHandle(Scene scene)
+ {
+ return scene.IsValid() && GetSceneHandleRaw(scene) != 0;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/FishNet/Runtime/UnityCompatibility.cs.meta b/Assets/FishNet/Runtime/UnityCompatibility.cs.meta
new file mode 100644
index 00000000..897e9ea9
--- /dev/null
+++ b/Assets/FishNet/Runtime/UnityCompatibility.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: c3a88ed478506c145a5efcd3e7c04fd6
\ No newline at end of file