Skip to content
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

feat(NetworkIdentity): Reuse Network IDs #3734

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
51 changes: 48 additions & 3 deletions Assets/Mirror/Core/NetworkIdentity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -269,17 +269,52 @@ internal static void ResetClientStatics()

internal static void ResetServerStatics()
{
reuseNetworkIds = true;
reuseDelay = 1;

netIdQueue.Clear();
nextNetworkId = 1;
}

/// <summary>Gets the NetworkIdentity from the sceneIds dictionary with the corresponding id</summary>
public static NetworkIdentity GetSceneIdentity(ulong id) => sceneIds[id];

#region Network ID Reuse

internal static bool reuseNetworkIds = true;
internal static byte reuseDelay = 1;

internal struct ReusableNetworkId
{
public uint reusableNetId;
public double timeAvailable;
}

// pool of NetworkIds that can be reused
internal static readonly Queue<ReusableNetworkId> netIdQueue = new Queue<ReusableNetworkId>();
static uint nextNetworkId = 1;
internal static uint GetNextNetworkId() => nextNetworkId++;

internal static uint GetNextNetworkId()
{
// Older Unity versions don't have TryPeek.
if (reuseNetworkIds && netIdQueue.Count > 0 && netIdQueue.Peek().timeAvailable < NetworkTime.time)
{
ReusableNetworkId nextNetId = netIdQueue.Dequeue();
//Debug.LogFormat(LogType.Log, LogOption.NoStacktrace, null, $"[GetNextNetworkId] Reusing NetworkId {nextNetId.reusableNetId}.");
return nextNetId.reusableNetId;
}

return nextNetworkId++;
}

/// <summary>Resets nextNetworkId = 1</summary>
public static void ResetNextNetworkId() => nextNetworkId = 1;
public static void ResetNextNetworkId()
{
netIdQueue.Clear();
nextNetworkId = 1;
}

#endregion

/// <summary>The delegate type for the clientAuthorityCallback.</summary>
public delegate void ClientAuthorityCallback(NetworkConnectionToClient conn, NetworkIdentity identity, bool authorityState);
Expand Down Expand Up @@ -633,6 +668,9 @@ void OnDestroy()
NetworkServer.Destroy(gameObject);
}

if (isServer && reuseNetworkIds && netId > 0)
netIdQueue.Enqueue(new ReusableNetworkId { reusableNetId = netId, timeAvailable = NetworkTime.time + reuseDelay });

if (isLocalPlayer)
{
// previously there was a bug where isLocalPlayer was
Expand Down Expand Up @@ -1327,7 +1365,14 @@ internal void ResetState()
isOwned = false;
NotifyAuthority();

netId = 0;
if (netId > 0)
{
if (reuseNetworkIds)
netIdQueue.Enqueue(new ReusableNetworkId { reusableNetId = netId, timeAvailable = NetworkTime.time + reuseDelay });

netId = 0;
}

connectionToServer = null;
connectionToClient = null;

Expand Down
11 changes: 11 additions & 0 deletions Assets/Mirror/Core/NetworkManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ public class NetworkManager : MonoBehaviour
// [Tooltip("Client broadcasts 'sendRate' times per second. Use around 60Hz for fast paced games like Counter-Strike to minimize latency. Use around 30Hz for games like WoW to minimize computations. Use around 1-10Hz for slow paced games like EVE.")]
// public int clientSendRate = 30; // 33 ms

[Header("Network ID Reuse")]
[Tooltip("Reuse network IDs when objects are unspawned or destroyed?")]
public bool reuseNetworkIds = true;
[Range(1, 60)]
[Tooltip("Delay in seconds before network IDs are reused")]
public byte reuseDelay = 1;

/// <summary>Automatically switch to this scene upon going offline (on start / on disconnect / on shutdown).</summary>
[Header("Scene Management")]
[Scene]
Expand Down Expand Up @@ -290,6 +297,10 @@ void SetupServer()
NetworkServer.disconnectInactiveTimeout = disconnectInactiveTimeout;
NetworkServer.exceptionsDisconnect = exceptionsDisconnect;

// Setup reuseable network IDs
NetworkIdentity.reuseNetworkIds = reuseNetworkIds;
NetworkIdentity.reuseDelay = reuseDelay;

if (runInBackground)
Application.runInBackground = true;

Expand Down
21 changes: 21 additions & 0 deletions Assets/Mirror/Editor/NetworkInformationPreview.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ public override void OnPreviewGUI(Rect r, GUIStyle background)

Y = DrawObservers(identity, initialX, Y);

Y = DrawNetworkIDQueue(initialX, Y);

_ = DrawOwner(identity, initialX, Y);

}
Expand Down Expand Up @@ -193,6 +195,25 @@ float DrawObservers(NetworkIdentity identity, float initialX, float Y)
return Y;
}

float DrawNetworkIDQueue(float initialX, float Y)
{
if (NetworkIdentity.netIdQueue.Count > 0)
{
Rect netIdRect = new Rect(initialX, Y + 10, 200, 20);
GUI.Label(netIdRect, new GUIContent("Network ID Queue"), styles.labelStyle);
netIdRect.x += 20;
netIdRect.y += netIdRect.height;
foreach (var entry in NetworkIdentity.netIdQueue)
{
GUI.Label(netIdRect, $"[{entry.reusableNetId}] {entry.timeAvailable:0.000}", styles.componentName);
netIdRect.y += netIdRect.height;
Y = netIdRect.y;
}
}

return Y;
}

float DrawOwner(NetworkIdentity identity, float initialX, float Y)
{
if (identity.connectionToClient != null)
Expand Down
Loading