From f40a7d311ddce11662772d4bf8d0f1481ee1c080 Mon Sep 17 00:00:00 2001 From: "M. Fatih MAR" Date: Fri, 5 Feb 2021 04:20:42 +0000 Subject: [PATCH 01/14] implement NetworkUpdateLoop --- .../Runtime/Core/NetworkUpdateLoop.cs | 446 ++++++++++++++++++ .../Runtime/Core/NetworkUpdateLoop.cs.meta | 11 + 2 files changed, 457 insertions(+) create mode 100644 com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs create mode 100644 com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs.meta diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs new file mode 100644 index 0000000000..706bf1d623 --- /dev/null +++ b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs @@ -0,0 +1,446 @@ +using UnityEngine; +using UnityEngine.LowLevel; +using UnityEngine.PlayerLoop; +using System.Linq; +using System.Collections.Generic; + +namespace MLAPI +{ + public interface INetworkUpdateSystem + { + void NetworkUpdate(); + } + + public enum NetworkUpdateStage : byte + { + Initialization = 1, + EarlyUpdate = 2, + FixedUpdate = 3, + PreUpdate = 4, + Update = 0, + PreLateUpdate = 5, + PostLateUpdate = 6 + } + + public static class NetworkUpdateLoop + { + [RuntimeInitializeOnLoadMethod] + private static void Initialize() + { + var customPlayerLoop = PlayerLoop.GetCurrentPlayerLoop(); + + for (int i = 0; i < customPlayerLoop.subSystemList.Length; i++) + { + var playerLoopSystem = customPlayerLoop.subSystemList[i]; + + if (playerLoopSystem.type == typeof(Initialization)) + { + var subsystems = playerLoopSystem.subSystemList.ToList(); + subsystems.Add(NetworkInitialization.CreateLoopSystem()); + playerLoopSystem.subSystemList = subsystems.ToArray(); + } + else if (playerLoopSystem.type == typeof(EarlyUpdate)) + { + var subsystems = playerLoopSystem.subSystemList.ToList(); + subsystems.Insert(0, NetworkEarlyUpdate.CreateLoopSystem()); + playerLoopSystem.subSystemList = subsystems.ToArray(); + } + else if (playerLoopSystem.type == typeof(FixedUpdate)) + { + var subsystems = playerLoopSystem.subSystemList.ToList(); + subsystems.Insert(0, NetworkFixedUpdate.CreateLoopSystem()); + playerLoopSystem.subSystemList = subsystems.ToArray(); + } + else if (playerLoopSystem.type == typeof(PreUpdate)) + { + var subsystems = playerLoopSystem.subSystemList.ToList(); + subsystems.Insert(0, NetworkPreUpdate.CreateLoopSystem()); + playerLoopSystem.subSystemList = subsystems.ToArray(); + } + else if (playerLoopSystem.type == typeof(Update)) + { + var subsystems = playerLoopSystem.subSystemList.ToList(); + subsystems.Insert(0, NetworkUpdate.CreateLoopSystem()); + playerLoopSystem.subSystemList = subsystems.ToArray(); + } + else if (playerLoopSystem.type == typeof(PreLateUpdate)) + { + var subsystems = playerLoopSystem.subSystemList.ToList(); + subsystems.Insert(0, NetworkPreLateUpdate.CreateLoopSystem()); + playerLoopSystem.subSystemList = subsystems.ToArray(); + } + else if (playerLoopSystem.type == typeof(PostLateUpdate)) + { + var subsystems = playerLoopSystem.subSystemList.ToList(); + subsystems.Add(NetworkPostLateUpdate.CreateLoopSystem()); + playerLoopSystem.subSystemList = subsystems.ToArray(); + } + + customPlayerLoop.subSystemList[i] = playerLoopSystem; + } + + PlayerLoop.SetPlayerLoop(customPlayerLoop); + } + + private struct NetworkInitialization + { + public static PlayerLoopSystem CreateLoopSystem() + { + return new PlayerLoopSystem + { + type = typeof(NetworkInitialization), + updateDelegate = RunNetworkInitialization + }; + } + } + + private struct NetworkEarlyUpdate + { + public static PlayerLoopSystem CreateLoopSystem() + { + return new PlayerLoopSystem + { + type = typeof(NetworkEarlyUpdate), + updateDelegate = RunNetworkEarlyUpdate + }; + } + } + + private struct NetworkFixedUpdate + { + public static PlayerLoopSystem CreateLoopSystem() + { + return new PlayerLoopSystem + { + type = typeof(NetworkFixedUpdate), + updateDelegate = RunNetworkFixedUpdate + }; + } + } + + private struct NetworkPreUpdate + { + public static PlayerLoopSystem CreateLoopSystem() + { + return new PlayerLoopSystem + { + type = typeof(NetworkPreUpdate), + updateDelegate = RunNetworkPreUpdate + }; + } + } + + private struct NetworkUpdate + { + public static PlayerLoopSystem CreateLoopSystem() + { + return new PlayerLoopSystem + { + type = typeof(NetworkUpdate), + updateDelegate = RunNetworkUpdate + }; + } + } + + private struct NetworkPreLateUpdate + { + public static PlayerLoopSystem CreateLoopSystem() + { + return new PlayerLoopSystem + { + type = typeof(NetworkPreLateUpdate), + updateDelegate = RunNetworkPreLateUpdate + }; + } + } + + private struct NetworkPostLateUpdate + { + public static PlayerLoopSystem CreateLoopSystem() + { + return new PlayerLoopSystem + { + type = typeof(NetworkPostLateUpdate), + updateDelegate = RunNetworkPostLateUpdate + }; + } + } + + public static void RegisterAllNetworkUpdates(this INetworkUpdateSystem updateSystem) + { + RegisterNetworkUpdate(updateSystem, NetworkUpdateStage.Initialization); + RegisterNetworkUpdate(updateSystem, NetworkUpdateStage.EarlyUpdate); + RegisterNetworkUpdate(updateSystem, NetworkUpdateStage.FixedUpdate); + RegisterNetworkUpdate(updateSystem, NetworkUpdateStage.PreUpdate); + RegisterNetworkUpdate(updateSystem, NetworkUpdateStage.Update); + RegisterNetworkUpdate(updateSystem, NetworkUpdateStage.PreLateUpdate); + RegisterNetworkUpdate(updateSystem, NetworkUpdateStage.PostLateUpdate); + } + + public static void RegisterNetworkUpdate(this INetworkUpdateSystem updateSystem, NetworkUpdateStage updateStage = NetworkUpdateStage.Update) + { + switch (updateStage) + { + case NetworkUpdateStage.Initialization: + { + if (!m_Initialization_List.Contains(updateSystem)) + { + m_Initialization_List.Add(updateSystem); + m_Initialization_Array = m_Initialization_List.ToArray(); + } + + break; + } + case NetworkUpdateStage.EarlyUpdate: + { + if (!m_EarlyUpdate_List.Contains(updateSystem)) + { + m_EarlyUpdate_List.Add(updateSystem); + m_EarlyUpdate_Array = m_EarlyUpdate_List.ToArray(); + } + + break; + } + case NetworkUpdateStage.FixedUpdate: + { + if (!m_FixedUpdate_List.Contains(updateSystem)) + { + m_FixedUpdate_List.Add(updateSystem); + m_FixedUpdate_Array = m_FixedUpdate_List.ToArray(); + } + + break; + } + case NetworkUpdateStage.PreUpdate: + { + if (!m_PreUpdate_List.Contains(updateSystem)) + { + m_PreUpdate_List.Add(updateSystem); + m_PreUpdate_Array = m_PreUpdate_List.ToArray(); + } + + break; + } + case NetworkUpdateStage.Update: + { + if (!m_Update_List.Contains(updateSystem)) + { + m_Update_List.Add(updateSystem); + m_Update_Array = m_Update_List.ToArray(); + } + + break; + } + case NetworkUpdateStage.PreLateUpdate: + { + if (!m_PreLateUpdate_List.Contains(updateSystem)) + { + m_PreLateUpdate_List.Add(updateSystem); + m_PreLateUpdate_Array = m_PreLateUpdate_List.ToArray(); + } + + break; + } + case NetworkUpdateStage.PostLateUpdate: + { + if (!m_PostLateUpdate_List.Contains(updateSystem)) + { + m_PostLateUpdate_List.Add(updateSystem); + m_PostLateUpdate_Array = m_PostLateUpdate_List.ToArray(); + } + + break; + } + } + } + + public static void UnregisterAllNetworkUpdates(this INetworkUpdateSystem updateSystem) + { + UnregisterNetworkUpdate(updateSystem, NetworkUpdateStage.Initialization); + UnregisterNetworkUpdate(updateSystem, NetworkUpdateStage.EarlyUpdate); + UnregisterNetworkUpdate(updateSystem, NetworkUpdateStage.FixedUpdate); + UnregisterNetworkUpdate(updateSystem, NetworkUpdateStage.PreUpdate); + UnregisterNetworkUpdate(updateSystem, NetworkUpdateStage.Update); + UnregisterNetworkUpdate(updateSystem, NetworkUpdateStage.PreLateUpdate); + UnregisterNetworkUpdate(updateSystem, NetworkUpdateStage.PostLateUpdate); + } + + public static void UnregisterNetworkUpdate(this INetworkUpdateSystem updateSystem, NetworkUpdateStage updateStage = NetworkUpdateStage.Update) + { + switch (updateStage) + { + case NetworkUpdateStage.Initialization: + { + if (m_Initialization_List.Contains(updateSystem)) + { + m_Initialization_List.Remove(updateSystem); + m_Initialization_Array = m_Initialization_List.ToArray(); + } + + break; + } + case NetworkUpdateStage.EarlyUpdate: + { + if (m_EarlyUpdate_List.Contains(updateSystem)) + { + m_EarlyUpdate_List.Remove(updateSystem); + m_EarlyUpdate_Array = m_EarlyUpdate_List.ToArray(); + } + + break; + } + case NetworkUpdateStage.FixedUpdate: + { + if (m_FixedUpdate_List.Contains(updateSystem)) + { + m_FixedUpdate_List.Remove(updateSystem); + m_FixedUpdate_Array = m_FixedUpdate_List.ToArray(); + } + + break; + } + case NetworkUpdateStage.PreUpdate: + { + if (m_PreUpdate_List.Contains(updateSystem)) + { + m_PreUpdate_List.Remove(updateSystem); + m_PreUpdate_Array = m_PreUpdate_List.ToArray(); + } + + break; + } + case NetworkUpdateStage.Update: + { + if (m_Update_List.Contains(updateSystem)) + { + m_Update_List.Remove(updateSystem); + m_Update_Array = m_Update_List.ToArray(); + } + + break; + } + case NetworkUpdateStage.PreLateUpdate: + { + if (m_PreLateUpdate_List.Contains(updateSystem)) + { + m_PreLateUpdate_List.Remove(updateSystem); + m_PreLateUpdate_Array = m_PreLateUpdate_List.ToArray(); + } + + break; + } + case NetworkUpdateStage.PostLateUpdate: + { + if (m_PostLateUpdate_List.Contains(updateSystem)) + { + m_PostLateUpdate_List.Remove(updateSystem); + m_PostLateUpdate_Array = m_PostLateUpdate_List.ToArray(); + } + + break; + } + } + } + + public static uint FrameCount = 0; + public static NetworkUpdateStage UpdateStage; + + private static void AdvanceFrame() + { + ++FrameCount; + } + + private static readonly List m_Initialization_List = new List(); + private static INetworkUpdateSystem[] m_Initialization_Array = new INetworkUpdateSystem[0]; + + private static void RunNetworkInitialization() + { + AdvanceFrame(); + + UpdateStage = NetworkUpdateStage.Initialization; + int arrayLength = m_Initialization_Array.Length; + for (int i = 0; i < arrayLength; i++) + { + m_Initialization_Array[i].NetworkUpdate(); + } + } + + private static readonly List m_EarlyUpdate_List = new List(); + private static INetworkUpdateSystem[] m_EarlyUpdate_Array = new INetworkUpdateSystem[0]; + + private static void RunNetworkEarlyUpdate() + { + UpdateStage = NetworkUpdateStage.EarlyUpdate; + int arrayLength = m_EarlyUpdate_Array.Length; + for (int i = 0; i < arrayLength; i++) + { + m_EarlyUpdate_Array[i].NetworkUpdate(); + } + } + + private static readonly List m_FixedUpdate_List = new List(); + private static INetworkUpdateSystem[] m_FixedUpdate_Array = new INetworkUpdateSystem[0]; + + private static void RunNetworkFixedUpdate() + { + UpdateStage = NetworkUpdateStage.FixedUpdate; + int arrayLength = m_FixedUpdate_Array.Length; + for (int i = 0; i < arrayLength; i++) + { + m_FixedUpdate_Array[i].NetworkUpdate(); + } + } + + private static readonly List m_PreUpdate_List = new List(); + private static INetworkUpdateSystem[] m_PreUpdate_Array = new INetworkUpdateSystem[0]; + + private static void RunNetworkPreUpdate() + { + UpdateStage = NetworkUpdateStage.PreUpdate; + int arrayLength = m_PreUpdate_Array.Length; + for (int i = 0; i < arrayLength; i++) + { + m_PreUpdate_Array[i].NetworkUpdate(); + } + } + + private static readonly List m_Update_List = new List(); + private static INetworkUpdateSystem[] m_Update_Array = new INetworkUpdateSystem[0]; + + private static void RunNetworkUpdate() + { + UpdateStage = NetworkUpdateStage.Update; + int arrayLength = m_Update_Array.Length; + for (int i = 0; i < arrayLength; i++) + { + m_Update_Array[i].NetworkUpdate(); + } + } + + private static readonly List m_PreLateUpdate_List = new List(); + private static INetworkUpdateSystem[] m_PreLateUpdate_Array = new INetworkUpdateSystem[0]; + + private static void RunNetworkPreLateUpdate() + { + UpdateStage = NetworkUpdateStage.PreLateUpdate; + int arrayLength = m_PreLateUpdate_Array.Length; + for (int i = 0; i < arrayLength; i++) + { + m_PreLateUpdate_Array[i].NetworkUpdate(); + } + } + + private static readonly List m_PostLateUpdate_List = new List(); + private static INetworkUpdateSystem[] m_PostLateUpdate_Array = new INetworkUpdateSystem[0]; + + private static void RunNetworkPostLateUpdate() + { + UpdateStage = NetworkUpdateStage.PostLateUpdate; + int arrayLength = m_PostLateUpdate_Array.Length; + for (int i = 0; i < arrayLength; i++) + { + m_PostLateUpdate_Array[i].NetworkUpdate(); + } + } + } +} \ No newline at end of file diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs.meta b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs.meta new file mode 100644 index 0000000000..403ee6e42d --- /dev/null +++ b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0cd9c24b9acfd4e82a71c795f37235c3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From 6da2c42d367876ec65c8607706cdddb3c0839eea Mon Sep 17 00:00:00 2001 From: "M. Fatih MAR" Date: Tue, 9 Feb 2021 22:53:56 +0000 Subject: [PATCH 02/14] remove AdvanceFrame() and FrameCount --- .../Runtime/Core/NetworkUpdateLoop.cs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs index 706bf1d623..1e2f703987 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs @@ -342,21 +342,13 @@ public static void UnregisterNetworkUpdate(this INetworkUpdateSystem updateSyste } } - public static uint FrameCount = 0; public static NetworkUpdateStage UpdateStage; - private static void AdvanceFrame() - { - ++FrameCount; - } - private static readonly List m_Initialization_List = new List(); private static INetworkUpdateSystem[] m_Initialization_Array = new INetworkUpdateSystem[0]; private static void RunNetworkInitialization() { - AdvanceFrame(); - UpdateStage = NetworkUpdateStage.Initialization; int arrayLength = m_Initialization_Array.Length; for (int i = 0; i < arrayLength; i++) From 7fe5c3be876170866ee3d1e94723a5978f923624 Mon Sep 17 00:00:00 2001 From: "M. Fatih MAR" Date: Wed, 10 Feb 2021 05:48:44 +0000 Subject: [PATCH 03/14] update player loop injection points and INetworkUpdateSystem API --- .../Runtime/Core/NetworkUpdateLoop.cs | 93 ++++++++++++++++--- 1 file changed, 78 insertions(+), 15 deletions(-) diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs index 1e2f703987..163b63e27a 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs @@ -8,7 +8,7 @@ namespace MLAPI { public interface INetworkUpdateSystem { - void NetworkUpdate(); + void NetworkUpdate(NetworkUpdateStage updateStage); } public enum NetworkUpdateStage : byte @@ -36,43 +36,106 @@ private static void Initialize() if (playerLoopSystem.type == typeof(Initialization)) { var subsystems = playerLoopSystem.subSystemList.ToList(); - subsystems.Add(NetworkInitialization.CreateLoopSystem()); + { + // insert at the bottom of `Initialization` + subsystems.Add(NetworkInitialization.CreateLoopSystem()); + } playerLoopSystem.subSystemList = subsystems.ToArray(); } else if (playerLoopSystem.type == typeof(EarlyUpdate)) { var subsystems = playerLoopSystem.subSystemList.ToList(); - subsystems.Insert(0, NetworkEarlyUpdate.CreateLoopSystem()); + { + int indexOfScriptRunDelayedStartupFrame = subsystems.FindIndex(s => s.type == typeof(EarlyUpdate.ScriptRunDelayedStartupFrame)); + if (indexOfScriptRunDelayedStartupFrame < 0) + { + Debug.LogError($"{nameof(NetworkUpdateLoop)}.{nameof(Initialize)}: Cannot find index of `{nameof(EarlyUpdate.ScriptRunDelayedStartupFrame)}` loop system in `{nameof(EarlyUpdate)}`'s subsystem list!"); + return; + } + + // insert before `EarlyUpdate.ScriptRunDelayedStartupFrame` + subsystems.Insert(indexOfScriptRunDelayedStartupFrame, NetworkEarlyUpdate.CreateLoopSystem()); + } playerLoopSystem.subSystemList = subsystems.ToArray(); } else if (playerLoopSystem.type == typeof(FixedUpdate)) { var subsystems = playerLoopSystem.subSystemList.ToList(); - subsystems.Insert(0, NetworkFixedUpdate.CreateLoopSystem()); + { + int indexOfScriptRunBehaviourFixedUpdate = subsystems.FindIndex(s => s.type == typeof(FixedUpdate.ScriptRunBehaviourFixedUpdate)); + if (indexOfScriptRunBehaviourFixedUpdate < 0) + { + Debug.LogError($"{nameof(NetworkUpdateLoop)}.{nameof(Initialize)}: Cannot find index of `{nameof(FixedUpdate.ScriptRunBehaviourFixedUpdate)}` loop system in `{nameof(FixedUpdate)}`'s subsystem list!"); + return; + } + + // insert before `FixedUpdate.ScriptRunBehaviourFixedUpdate` + subsystems.Insert(indexOfScriptRunBehaviourFixedUpdate, NetworkFixedUpdate.CreateLoopSystem()); + } playerLoopSystem.subSystemList = subsystems.ToArray(); } else if (playerLoopSystem.type == typeof(PreUpdate)) { var subsystems = playerLoopSystem.subSystemList.ToList(); - subsystems.Insert(0, NetworkPreUpdate.CreateLoopSystem()); + { + int indexOfPhysicsUpdate = subsystems.FindIndex(s => s.type == typeof(PreUpdate.PhysicsUpdate)); + if (indexOfPhysicsUpdate < 0) + { + Debug.LogError($"{nameof(NetworkUpdateLoop)}.{nameof(Initialize)}: Cannot find index of `{nameof(PreUpdate.PhysicsUpdate)}` loop system in `{nameof(PreUpdate)}`'s subsystem list!"); + return; + } + + // insert before `PreUpdate.PhysicsUpdate` + subsystems.Insert(indexOfPhysicsUpdate, NetworkPreUpdate.CreateLoopSystem()); + } playerLoopSystem.subSystemList = subsystems.ToArray(); } else if (playerLoopSystem.type == typeof(Update)) { var subsystems = playerLoopSystem.subSystemList.ToList(); - subsystems.Insert(0, NetworkUpdate.CreateLoopSystem()); + { + int indexOfScriptRunBehaviourUpdate = subsystems.FindIndex(s => s.type == typeof(Update.ScriptRunBehaviourUpdate)); + if (indexOfScriptRunBehaviourUpdate < 0) + { + Debug.LogError($"{nameof(NetworkUpdateLoop)}.{nameof(Initialize)}: Cannot find index of `{nameof(Update.ScriptRunBehaviourUpdate)}` loop system in `{nameof(Update)}`'s subsystem list!"); + return; + } + + // insert before `Update.ScriptRunBehaviourUpdate` + subsystems.Insert(indexOfScriptRunBehaviourUpdate, NetworkUpdate.CreateLoopSystem()); + } playerLoopSystem.subSystemList = subsystems.ToArray(); } else if (playerLoopSystem.type == typeof(PreLateUpdate)) { var subsystems = playerLoopSystem.subSystemList.ToList(); - subsystems.Insert(0, NetworkPreLateUpdate.CreateLoopSystem()); + { + int indexOfScriptRunBehaviourLateUpdate = subsystems.FindIndex(s => s.type == typeof(PreLateUpdate.ScriptRunBehaviourLateUpdate)); + if (indexOfScriptRunBehaviourLateUpdate < 0) + { + Debug.LogError($"{nameof(NetworkUpdateLoop)}.{nameof(Initialize)}: Cannot find index of `{nameof(PreLateUpdate.ScriptRunBehaviourLateUpdate)}` loop system in `{nameof(PreLateUpdate)}`'s subsystem list!"); + return; + } + + // insert before `PreLateUpdate.ScriptRunBehaviourLateUpdate` + subsystems.Insert(indexOfScriptRunBehaviourLateUpdate, NetworkPreLateUpdate.CreateLoopSystem()); + } playerLoopSystem.subSystemList = subsystems.ToArray(); } else if (playerLoopSystem.type == typeof(PostLateUpdate)) { var subsystems = playerLoopSystem.subSystemList.ToList(); - subsystems.Add(NetworkPostLateUpdate.CreateLoopSystem()); + { + int indexOfPlayerSendFrameComplete = subsystems.FindIndex(s => s.type == typeof(PostLateUpdate.PlayerSendFrameComplete)); + if (indexOfPlayerSendFrameComplete < 0) + { + Debug.LogError($"{nameof(NetworkUpdateLoop)}.{nameof(Initialize)}: Cannot find index of `{nameof(PostLateUpdate.PlayerSendFrameComplete)}` loop system in `{nameof(PostLateUpdate)}`'s subsystem list!"); + return; + } + + // insert after `PostLateUpdate.PlayerSendFrameComplete` + subsystems.Insert(indexOfPlayerSendFrameComplete + 1, NetworkPostLateUpdate.CreateLoopSystem()); + } playerLoopSystem.subSystemList = subsystems.ToArray(); } @@ -353,7 +416,7 @@ private static void RunNetworkInitialization() int arrayLength = m_Initialization_Array.Length; for (int i = 0; i < arrayLength; i++) { - m_Initialization_Array[i].NetworkUpdate(); + m_Initialization_Array[i].NetworkUpdate(UpdateStage); } } @@ -366,7 +429,7 @@ private static void RunNetworkEarlyUpdate() int arrayLength = m_EarlyUpdate_Array.Length; for (int i = 0; i < arrayLength; i++) { - m_EarlyUpdate_Array[i].NetworkUpdate(); + m_EarlyUpdate_Array[i].NetworkUpdate(UpdateStage); } } @@ -379,7 +442,7 @@ private static void RunNetworkFixedUpdate() int arrayLength = m_FixedUpdate_Array.Length; for (int i = 0; i < arrayLength; i++) { - m_FixedUpdate_Array[i].NetworkUpdate(); + m_FixedUpdate_Array[i].NetworkUpdate(UpdateStage); } } @@ -392,7 +455,7 @@ private static void RunNetworkPreUpdate() int arrayLength = m_PreUpdate_Array.Length; for (int i = 0; i < arrayLength; i++) { - m_PreUpdate_Array[i].NetworkUpdate(); + m_PreUpdate_Array[i].NetworkUpdate(UpdateStage); } } @@ -405,7 +468,7 @@ private static void RunNetworkUpdate() int arrayLength = m_Update_Array.Length; for (int i = 0; i < arrayLength; i++) { - m_Update_Array[i].NetworkUpdate(); + m_Update_Array[i].NetworkUpdate(UpdateStage); } } @@ -418,7 +481,7 @@ private static void RunNetworkPreLateUpdate() int arrayLength = m_PreLateUpdate_Array.Length; for (int i = 0; i < arrayLength; i++) { - m_PreLateUpdate_Array[i].NetworkUpdate(); + m_PreLateUpdate_Array[i].NetworkUpdate(UpdateStage); } } @@ -431,7 +494,7 @@ private static void RunNetworkPostLateUpdate() int arrayLength = m_PostLateUpdate_Array.Length; for (int i = 0; i < arrayLength; i++) { - m_PostLateUpdate_Array[i].NetworkUpdate(); + m_PostLateUpdate_Array[i].NetworkUpdate(UpdateStage); } } } From 379102bc7c7e6f0402863429b39afcd547cb3ffe Mon Sep 17 00:00:00 2001 From: "M. Fatih MAR" Date: Thu, 11 Feb 2021 22:05:19 +0000 Subject: [PATCH 04/14] add xmldoc and notes --- .../Runtime/Core/NetworkUpdateLoop.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs index 163b63e27a..0fd6b4bab6 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs @@ -6,11 +6,15 @@ namespace MLAPI { + /// + /// The required interface of a network update system being updated by the network update loop. + /// public interface INetworkUpdateSystem { void NetworkUpdate(NetworkUpdateStage updateStage); } + // todo: XML-doc public enum NetworkUpdateStage : byte { Initialization = 1, @@ -22,6 +26,9 @@ public enum NetworkUpdateStage : byte PostLateUpdate = 6 } + /// + /// The class representing the network update loop injected into low-level player loop in Unity. + /// public static class NetworkUpdateLoop { [RuntimeInitializeOnLoadMethod] @@ -229,6 +236,7 @@ public static PlayerLoopSystem CreateLoopSystem() } } + // todo: XML-doc public static void RegisterAllNetworkUpdates(this INetworkUpdateSystem updateSystem) { RegisterNetworkUpdate(updateSystem, NetworkUpdateStage.Initialization); @@ -240,6 +248,7 @@ public static void RegisterAllNetworkUpdates(this INetworkUpdateSystem updateSys RegisterNetworkUpdate(updateSystem, NetworkUpdateStage.PostLateUpdate); } + // todo: XML-doc public static void RegisterNetworkUpdate(this INetworkUpdateSystem updateSystem, NetworkUpdateStage updateStage = NetworkUpdateStage.Update) { switch (updateStage) @@ -317,6 +326,7 @@ public static void RegisterNetworkUpdate(this INetworkUpdateSystem updateSystem, } } + // todo: XML-doc public static void UnregisterAllNetworkUpdates(this INetworkUpdateSystem updateSystem) { UnregisterNetworkUpdate(updateSystem, NetworkUpdateStage.Initialization); @@ -328,6 +338,7 @@ public static void UnregisterAllNetworkUpdates(this INetworkUpdateSystem updateS UnregisterNetworkUpdate(updateSystem, NetworkUpdateStage.PostLateUpdate); } + // todo: XML-doc public static void UnregisterNetworkUpdate(this INetworkUpdateSystem updateSystem, NetworkUpdateStage updateStage = NetworkUpdateStage.Update) { switch (updateStage) @@ -405,6 +416,7 @@ public static void UnregisterNetworkUpdate(this INetworkUpdateSystem updateSyste } } + // todo: XML-doc public static NetworkUpdateStage UpdateStage; private static readonly List m_Initialization_List = new List(); From 2c08e60f1073cfd7dfe28bf1aff8cf0183ab009c Mon Sep 17 00:00:00 2001 From: "M. Fatih MAR" Date: Sat, 13 Feb 2021 20:53:11 +0000 Subject: [PATCH 05/14] add NetworkUpdateLoopTests --- .../Runtime/Core/NetworkUpdateLoop.cs | 6 +- .../Tests/Runtime/NetworkUpdateLoopTests.cs | 125 ++++++++++++++++++ ...cs.meta => NetworkUpdateLoopTests.cs.meta} | 0 .../Tests/Runtime/PlaceholderTests.cs | 12 -- 4 files changed, 128 insertions(+), 15 deletions(-) create mode 100644 com.unity.multiplayer.mlapi/Tests/Runtime/NetworkUpdateLoopTests.cs rename com.unity.multiplayer.mlapi/Tests/Runtime/{PlaceholderTests.cs.meta => NetworkUpdateLoopTests.cs.meta} (100%) delete mode 100644 com.unity.multiplayer.mlapi/Tests/Runtime/PlaceholderTests.cs diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs index 0fd6b4bab6..ef9789530e 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs @@ -1,8 +1,8 @@ -using UnityEngine; +using System.Linq; +using System.Collections.Generic; +using UnityEngine; using UnityEngine.LowLevel; using UnityEngine.PlayerLoop; -using System.Linq; -using System.Collections.Generic; namespace MLAPI { diff --git a/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkUpdateLoopTests.cs b/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkUpdateLoopTests.cs new file mode 100644 index 0000000000..6ec56c2aa7 --- /dev/null +++ b/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkUpdateLoopTests.cs @@ -0,0 +1,125 @@ +using System; +using System.Collections; +using NUnit.Framework; +using UnityEngine; +using UnityEngine.TestTools; + +namespace MLAPI.RuntimeTests +{ + public class NetworkUpdateLoopTests + { + [SetUp] + public void Setup() + { + } + + [TearDown] + public void Teardown() + { + } + + private struct NetworkUpdateCallbacks + { + public Action OnInitialization; + public Action OnEarlyUpdate; + public Action OnFixedUpdate; + public Action OnPreUpdate; + public Action OnUpdate; + public Action OnPreLateUpdate; + public Action OnPostLateUpdate; + } + + private class MyPlainScript : IDisposable, INetworkUpdateSystem + { + public NetworkUpdateCallbacks UpdateCallbacks; + + public void Initialize() + { + this.RegisterAllNetworkUpdates(); + } + + public void NetworkUpdate(NetworkUpdateStage updateStage) + { + // todo + } + + public void Dispose() + { + this.UnregisterAllNetworkUpdates(); + } + } + + [UnityTest] + public IEnumerator UpdateStagesPlainStandard() + { + // todo + yield return new WaitForEndOfFrame(); + } + + private struct MonoBehaviourCallbacks + { + public Action OnFixedUpdate; + public Action OnUpdate; + public Action OnLateUpdate; + public Action OnGUI; + } + + private class MyGameScript : MonoBehaviour, INetworkUpdateSystem + { + public NetworkUpdateCallbacks UpdateCallbacks; + public MonoBehaviourCallbacks BehaviourCallbacks; + + private void Awake() + { + this.RegisterNetworkUpdate(); + } + + public void NetworkUpdate(NetworkUpdateStage updateStage) + { + // todo + } + + private void OnDestroy() + { + this.UnregisterNetworkUpdate(); + } + } + + [UnityTest] + public IEnumerator UpdateStagesMonoBehaviour() + { + // todo + yield return new WaitForEndOfFrame(); + } + + private class MyComplexScript : IDisposable, INetworkUpdateSystem + { + public NetworkUpdateCallbacks UpdateCallbacks; + public MonoBehaviourCallbacks BehaviourCallbacks; + + public void Initialize() + { + this.RegisterNetworkUpdate(NetworkUpdateStage.EarlyUpdate); + this.RegisterNetworkUpdate(NetworkUpdateStage.FixedUpdate); + this.RegisterNetworkUpdate(NetworkUpdateStage.PostLateUpdate); + } + + public void NetworkUpdate(NetworkUpdateStage updateStage) + { + // todo + } + + public void Dispose() + { + this.UnregisterAllNetworkUpdates(); + } + } + + [UnityTest] + public IEnumerator UpdateStagesMultipleMixed() + { + // todo + yield return new WaitForEndOfFrame(); + } + } +} \ No newline at end of file diff --git a/com.unity.multiplayer.mlapi/Tests/Runtime/PlaceholderTests.cs.meta b/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkUpdateLoopTests.cs.meta similarity index 100% rename from com.unity.multiplayer.mlapi/Tests/Runtime/PlaceholderTests.cs.meta rename to com.unity.multiplayer.mlapi/Tests/Runtime/NetworkUpdateLoopTests.cs.meta diff --git a/com.unity.multiplayer.mlapi/Tests/Runtime/PlaceholderTests.cs b/com.unity.multiplayer.mlapi/Tests/Runtime/PlaceholderTests.cs deleted file mode 100644 index a81075798d..0000000000 --- a/com.unity.multiplayer.mlapi/Tests/Runtime/PlaceholderTests.cs +++ /dev/null @@ -1,12 +0,0 @@ -using NUnit.Framework; - -namespace MLAPI.RuntimeTests -{ - public class PlaceholderTests - { - [Test] - public void Foo() - { - } - } -} \ No newline at end of file From c891ddf5ca5aed9b4fbbf224f95bed2446a1fa43 Mon Sep 17 00:00:00 2001 From: "M. Fatih MAR" Date: Tue, 16 Feb 2021 05:11:58 +0000 Subject: [PATCH 06/14] implement NetworkUpdateLoop plain and mixed tests --- .../Tests/Runtime/NetworkUpdateLoopTests.cs | 256 +++++++++++++++--- 1 file changed, 214 insertions(+), 42 deletions(-) diff --git a/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkUpdateLoopTests.cs b/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkUpdateLoopTests.cs index 6ec56c2aa7..4778902037 100644 --- a/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkUpdateLoopTests.cs +++ b/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkUpdateLoopTests.cs @@ -1,23 +1,13 @@ using System; using System.Collections; -using NUnit.Framework; using UnityEngine; using UnityEngine.TestTools; +using NUnit.Framework; namespace MLAPI.RuntimeTests { public class NetworkUpdateLoopTests { - [SetUp] - public void Setup() - { - } - - [TearDown] - public void Teardown() - { - } - private struct NetworkUpdateCallbacks { public Action OnInitialization; @@ -35,12 +25,36 @@ private class MyPlainScript : IDisposable, INetworkUpdateSystem public void Initialize() { - this.RegisterAllNetworkUpdates(); + this.RegisterNetworkUpdate(NetworkUpdateStage.EarlyUpdate); + this.RegisterNetworkUpdate(NetworkUpdateStage.PreLateUpdate); } public void NetworkUpdate(NetworkUpdateStage updateStage) { - // todo + switch (updateStage) + { + case NetworkUpdateStage.Initialization: + UpdateCallbacks.OnInitialization(); + break; + case NetworkUpdateStage.EarlyUpdate: + UpdateCallbacks.OnEarlyUpdate(); + break; + case NetworkUpdateStage.FixedUpdate: + UpdateCallbacks.OnFixedUpdate(); + break; + case NetworkUpdateStage.PreUpdate: + UpdateCallbacks.OnPreUpdate(); + break; + case NetworkUpdateStage.Update: + UpdateCallbacks.OnUpdate(); + break; + case NetworkUpdateStage.PreLateUpdate: + UpdateCallbacks.OnPreLateUpdate(); + break; + case NetworkUpdateStage.PostLateUpdate: + UpdateCallbacks.OnPostLateUpdate(); + break; + } } public void Dispose() @@ -50,10 +64,91 @@ public void Dispose() } [UnityTest] - public IEnumerator UpdateStagesPlainStandard() + public IEnumerator UpdateStagesPlain() { - // todo + const int kNetInitializationIndex = 0; + const int kNetEarlyUpdateIndex = 1; + const int kNetFixedUpdateIndex = 2; + const int kNetPreUpdateIndex = 3; + const int kNetUpdateIndex = 4; + const int kNetPreLateUpdateIndex = 5; + const int kNetPostLateUpdateIndex = 6; + int[] netUpdates = new int[7]; + yield return new WaitForEndOfFrame(); + bool isTesting = false; + + using (var plainScript = new MyPlainScript()) + { + plainScript.UpdateCallbacks = new NetworkUpdateCallbacks + { + OnInitialization = () => + { + if (isTesting) + { + netUpdates[kNetInitializationIndex]++; + } + }, + OnEarlyUpdate = () => + { + if (isTesting) + { + netUpdates[kNetEarlyUpdateIndex]++; + } + }, + OnFixedUpdate = () => + { + if (isTesting) + { + netUpdates[kNetFixedUpdateIndex]++; + } + }, + OnPreUpdate = () => + { + if (isTesting) + { + netUpdates[kNetPreUpdateIndex]++; + } + }, + OnUpdate = () => + { + if (isTesting) + { + netUpdates[kNetUpdateIndex]++; + } + }, + OnPreLateUpdate = () => + { + if (isTesting) + { + netUpdates[kNetPreLateUpdateIndex]++; + } + }, + OnPostLateUpdate = () => + { + if (isTesting) + { + netUpdates[kNetPostLateUpdateIndex]++; + } + } + }; + + plainScript.Initialize(); + yield return new WaitForEndOfFrame(); + isTesting = true; + + for (int i = 0; i < 16; i++) + { + Assert.AreEqual(0, netUpdates[kNetInitializationIndex]); + Assert.AreEqual(i, netUpdates[kNetEarlyUpdateIndex]); + Assert.AreEqual(0, netUpdates[kNetFixedUpdateIndex]); + Assert.AreEqual(0, netUpdates[kNetPreUpdateIndex]); + Assert.AreEqual(0, netUpdates[kNetUpdateIndex]); + Assert.AreEqual(i, netUpdates[kNetPreLateUpdateIndex]); + Assert.AreEqual(0, netUpdates[kNetPostLateUpdateIndex]); + yield return new WaitForEndOfFrame(); + } + } } private struct MonoBehaviourCallbacks @@ -61,7 +156,6 @@ private struct MonoBehaviourCallbacks public Action OnFixedUpdate; public Action OnUpdate; public Action OnLateUpdate; - public Action OnGUI; } private class MyGameScript : MonoBehaviour, INetworkUpdateSystem @@ -71,55 +165,133 @@ private class MyGameScript : MonoBehaviour, INetworkUpdateSystem private void Awake() { - this.RegisterNetworkUpdate(); + this.RegisterNetworkUpdate(NetworkUpdateStage.FixedUpdate); + this.RegisterNetworkUpdate(NetworkUpdateStage.PreUpdate); + this.RegisterNetworkUpdate(NetworkUpdateStage.PreLateUpdate); } public void NetworkUpdate(NetworkUpdateStage updateStage) { - // todo + switch (updateStage) + { + case NetworkUpdateStage.FixedUpdate: + UpdateCallbacks.OnFixedUpdate(); + break; + case NetworkUpdateStage.PreUpdate: + UpdateCallbacks.OnPreUpdate(); + break; + case NetworkUpdateStage.PreLateUpdate: + UpdateCallbacks.OnPreLateUpdate(); + break; + } } - private void OnDestroy() + private void FixedUpdate() { - this.UnregisterNetworkUpdate(); + BehaviourCallbacks.OnFixedUpdate(); } - } - - [UnityTest] - public IEnumerator UpdateStagesMonoBehaviour() - { - // todo - yield return new WaitForEndOfFrame(); - } - - private class MyComplexScript : IDisposable, INetworkUpdateSystem - { - public NetworkUpdateCallbacks UpdateCallbacks; - public MonoBehaviourCallbacks BehaviourCallbacks; - public void Initialize() + private void Update() { - this.RegisterNetworkUpdate(NetworkUpdateStage.EarlyUpdate); - this.RegisterNetworkUpdate(NetworkUpdateStage.FixedUpdate); - this.RegisterNetworkUpdate(NetworkUpdateStage.PostLateUpdate); + BehaviourCallbacks.OnUpdate(); } - public void NetworkUpdate(NetworkUpdateStage updateStage) + private void LateUpdate() { - // todo + BehaviourCallbacks.OnLateUpdate(); } - public void Dispose() + private void OnDestroy() { this.UnregisterAllNetworkUpdates(); } } [UnityTest] - public IEnumerator UpdateStagesMultipleMixed() + public IEnumerator UpdateStagesMixed() { - // todo + const int kNetFixedUpdateIndex = 0; + const int kNetPreUpdateIndex = 1; + const int kNetPreLateUpdateIndex = 2; + int[] netUpdates = new int[3]; + const int kMonoFixedUpdateIndex = 0; + const int kMonoUpdateIndex = 1; + const int kMonoLateUpdateIndex = 2; + int[] monoUpdates = new int[3]; + yield return new WaitForEndOfFrame(); + bool isTesting = false; + + { + var gameObject = new GameObject($"{nameof(NetworkUpdateLoopTests)}.{nameof(UpdateStagesMixed)} (Dummy)"); + var gameScript = gameObject.AddComponent(); + gameScript.UpdateCallbacks = new NetworkUpdateCallbacks + { + OnFixedUpdate = () => + { + if (isTesting) + { + netUpdates[kNetFixedUpdateIndex]++; + Assert.AreEqual(monoUpdates[kMonoFixedUpdateIndex] + 1, netUpdates[kNetFixedUpdateIndex]); + } + }, + OnPreUpdate = () => + { + if (isTesting) + { + netUpdates[kNetPreUpdateIndex]++; + Assert.AreEqual(monoUpdates[kMonoUpdateIndex] + 1, netUpdates[kNetPreUpdateIndex]); + } + }, + OnPreLateUpdate = () => + { + if (isTesting) + { + netUpdates[kNetPreLateUpdateIndex]++; + Assert.AreEqual(monoUpdates[kMonoLateUpdateIndex] + 1, netUpdates[kNetPreLateUpdateIndex]); + } + } + }; + gameScript.BehaviourCallbacks = new MonoBehaviourCallbacks + { + OnFixedUpdate = () => + { + if (isTesting) + { + monoUpdates[kMonoFixedUpdateIndex]++; + Assert.AreEqual(netUpdates[kNetFixedUpdateIndex], monoUpdates[kMonoFixedUpdateIndex]); + } + }, + OnUpdate = () => + { + if (isTesting) + { + monoUpdates[kMonoUpdateIndex]++; + Assert.AreEqual(netUpdates[kNetPreUpdateIndex], monoUpdates[kMonoUpdateIndex]); + } + }, + OnLateUpdate = () => + { + if (isTesting) + { + monoUpdates[kMonoLateUpdateIndex]++; + Assert.AreEqual(netUpdates[kNetPreLateUpdateIndex], monoUpdates[kMonoLateUpdateIndex]); + } + } + }; + + yield return new WaitForEndOfFrame(); + isTesting = true; + + for (int i = 0; i < 16; i++) + { + Assert.AreEqual(i, netUpdates[kNetPreUpdateIndex]); + Assert.AreEqual(netUpdates[kNetPreUpdateIndex], monoUpdates[kMonoUpdateIndex]); + yield return new WaitForEndOfFrame(); + } + + GameObject.DestroyImmediate(gameObject); + } } } } \ No newline at end of file From 558599f9f6a15acd74772239d4f545ed69014a4f Mon Sep 17 00:00:00 2001 From: "M. Fatih MAR" Date: Tue, 16 Feb 2021 05:53:09 +0000 Subject: [PATCH 07/14] update xmldoc --- .../Runtime/Core/NetworkUpdateLoop.cs | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs index ef9789530e..3354a0158c 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs @@ -7,14 +7,16 @@ namespace MLAPI { /// - /// The required interface of a network update system being updated by the network update loop. + /// Defines the required interface of a network update system being executed by the network update loop. /// public interface INetworkUpdateSystem { void NetworkUpdate(NetworkUpdateStage updateStage); } - // todo: XML-doc + /// + /// Defines network update stages being executed by the network update loop. + /// public enum NetworkUpdateStage : byte { Initialization = 1, @@ -27,7 +29,7 @@ public enum NetworkUpdateStage : byte } /// - /// The class representing the network update loop injected into low-level player loop in Unity. + /// Represents the network update loop injected into low-level player loop in Unity. /// public static class NetworkUpdateLoop { @@ -236,7 +238,9 @@ public static PlayerLoopSystem CreateLoopSystem() } } - // todo: XML-doc + /// + /// Registers a network update system to be executed in all network update stages. + /// public static void RegisterAllNetworkUpdates(this INetworkUpdateSystem updateSystem) { RegisterNetworkUpdate(updateSystem, NetworkUpdateStage.Initialization); @@ -248,7 +252,9 @@ public static void RegisterAllNetworkUpdates(this INetworkUpdateSystem updateSys RegisterNetworkUpdate(updateSystem, NetworkUpdateStage.PostLateUpdate); } - // todo: XML-doc + /// + /// Registers a network update system to be executed in a specific network update stage. + /// public static void RegisterNetworkUpdate(this INetworkUpdateSystem updateSystem, NetworkUpdateStage updateStage = NetworkUpdateStage.Update) { switch (updateStage) @@ -326,7 +332,9 @@ public static void RegisterNetworkUpdate(this INetworkUpdateSystem updateSystem, } } - // todo: XML-doc + /// + /// Unregisters a network update system from all network update stages. + /// public static void UnregisterAllNetworkUpdates(this INetworkUpdateSystem updateSystem) { UnregisterNetworkUpdate(updateSystem, NetworkUpdateStage.Initialization); @@ -338,7 +346,9 @@ public static void UnregisterAllNetworkUpdates(this INetworkUpdateSystem updateS UnregisterNetworkUpdate(updateSystem, NetworkUpdateStage.PostLateUpdate); } - // todo: XML-doc + /// + /// Unregisters a network update system from a specific network update stage. + /// public static void UnregisterNetworkUpdate(this INetworkUpdateSystem updateSystem, NetworkUpdateStage updateStage = NetworkUpdateStage.Update) { switch (updateStage) @@ -416,7 +426,9 @@ public static void UnregisterNetworkUpdate(this INetworkUpdateSystem updateSyste } } - // todo: XML-doc + /// + /// The current network update stage being executed. + /// public static NetworkUpdateStage UpdateStage; private static readonly List m_Initialization_List = new List(); From 7837599eeceaccc37d828a371b3880a925941aba Mon Sep 17 00:00:00 2001 From: "M. Fatih MAR" Date: Tue, 16 Feb 2021 06:24:19 +0000 Subject: [PATCH 08/14] small meta fix --- .../Runtime/Messaging/{RPCQueue.meta => RpcQueue.meta} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename com.unity.multiplayer.mlapi/Runtime/Messaging/{RPCQueue.meta => RpcQueue.meta} (100%) diff --git a/com.unity.multiplayer.mlapi/Runtime/Messaging/RPCQueue.meta b/com.unity.multiplayer.mlapi/Runtime/Messaging/RpcQueue.meta similarity index 100% rename from com.unity.multiplayer.mlapi/Runtime/Messaging/RPCQueue.meta rename to com.unity.multiplayer.mlapi/Runtime/Messaging/RpcQueue.meta From db058d732147982446160bfba7f3b87b58c8d3e0 Mon Sep 17 00:00:00 2001 From: "M. Fatih MAR" Date: Tue, 16 Feb 2021 07:21:08 +0000 Subject: [PATCH 09/14] replace old network update loop with new RFC-backed network update loop --- .../Runtime/Core/NetworkUpdateLoopSystem.cs | 129 -------- .../Core/NetworkUpdateLoopSystem.cs.meta | 11 - .../Runtime/Core/NetworkUpdateManager.cs | 306 ------------------ .../Runtime/Core/NetworkUpdateManager.cs.meta | 11 - .../Runtime/Core/NetworkedBehaviour.cs | 51 +-- .../Runtime/Core/NetworkingManager.cs | 99 +++--- .../Runtime/Messaging/RpcParams.cs | 8 +- .../Messaging/RpcQueue/QueueHistoryFrame.cs | 4 +- .../Messaging/RpcQueue/RpcFrameQueueItem.cs | 2 +- .../Messaging/RpcQueue/RpcQueueContainer.cs | 155 +++------ .../Messaging/RpcQueue/RpcQueueProcessor.cs | 8 +- .../Runtime/Spawning/SpawnManager.cs | 3 +- 12 files changed, 104 insertions(+), 683 deletions(-) delete mode 100644 com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoopSystem.cs delete mode 100644 com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoopSystem.cs.meta delete mode 100644 com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateManager.cs delete mode 100644 com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateManager.cs.meta diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoopSystem.cs b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoopSystem.cs deleted file mode 100644 index 9b524ddf50..0000000000 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoopSystem.cs +++ /dev/null @@ -1,129 +0,0 @@ -using System; -using UnityEngine; - - -namespace MLAPI -{ - /// - /// NetworkUpdateLoopBehaviour - /// Derive from this class if you need to register a NetworkedBehaviour based class - /// - public class NetworkUpdateLoopBehaviour:NetworkedBehaviour, INetworkUpdateLoopSystem - { - protected virtual Action InternalRegisterNetworkUpdateStage(NetworkUpdateManager.NetworkUpdateStage stage ) - { - return null; - } - - public Action RegisterUpdate(NetworkUpdateManager.NetworkUpdateStage stage ) - { - return InternalRegisterNetworkUpdateStage(stage); - } - - protected void RegisterUpdateLoopSystem() - { - NetworkUpdateManager.NetworkLoopRegistration(this); - } - - protected void OnNetworkLoopSystemRemove() - { - if(onNetworkLoopSystemDestroyed != null) - { - onNetworkLoopSystemDestroyed.Invoke(this); - } - } - - private Action onNetworkLoopSystemDestroyed; - - public void RegisterUpdateLoopSystemDestroyCallback(Action networkLoopSystemDestroyedCallback) - { - onNetworkLoopSystemDestroyed = networkLoopSystemDestroyedCallback; - } - } - - /// - /// UpdateLoopBehaviour - /// Derive from this class if you only require MonoBehaviour functionality - /// - public class UpdateLoopBehaviour:MonoBehaviour, INetworkUpdateLoopSystem - { - protected virtual Action InternalRegisterNetworkUpdateStage(NetworkUpdateManager.NetworkUpdateStage stage ) - { - return null; - } - - public Action RegisterUpdate(NetworkUpdateManager.NetworkUpdateStage stage ) - { - return InternalRegisterNetworkUpdateStage(stage); - } - - protected void RegisterUpdateLoopSystem() - { - NetworkUpdateManager.NetworkLoopRegistration(this); - } - - protected void OnNetworkLoopSystemRemove() - { - if(onNetworkLoopSystemDestroyed != null) - { - onNetworkLoopSystemDestroyed.Invoke(this); - } - } - - private Action onNetworkLoopSystemDestroyed; - - public void RegisterUpdateLoopSystemDestroyCallback(Action networkLoopSystemDestroyedCallback) - { - onNetworkLoopSystemDestroyed = networkLoopSystemDestroyedCallback; - } - } - - /// - /// GenericUpdateLoopSystem - /// Derive from this class for generic (non-MonoBehaviour) classes - /// - public class GenericUpdateLoopSystem:INetworkUpdateLoopSystem - { - protected virtual Action InternalRegisterNetworkUpdateStage(NetworkUpdateManager.NetworkUpdateStage stage ) - { - return null; - } - - public Action RegisterUpdate(NetworkUpdateManager.NetworkUpdateStage stage ) - { - return InternalRegisterNetworkUpdateStage(stage); - } - - protected void RegisterUpdateLoopSystem() - { - NetworkUpdateManager.NetworkLoopRegistration(this); - } - - protected void OnNetworkLoopSystemRemove() - { - if(onNetworkLoopSystemDestroyed != null) - { - onNetworkLoopSystemDestroyed.Invoke(this); - } - } - - private Action onNetworkLoopSystemDestroyed; - - public void RegisterUpdateLoopSystemDestroyCallback(Action networkLoopSystemDestroyedCallback) - { - onNetworkLoopSystemDestroyed = networkLoopSystemDestroyedCallback; - } - } - - - /// - /// INetworkUpdateLoopSystem - /// Use this interface if you need a custom class beyond the scope of GenericUpdateLoopSystem, UpdateLoopBehaviour, and NetworkUpdateLoopBehaviour - /// - public interface INetworkUpdateLoopSystem - { - Action RegisterUpdate(NetworkUpdateManager.NetworkUpdateStage stage ); - - void RegisterUpdateLoopSystemDestroyCallback(Action networkLoopSystemDestroyedCallbsack); - } -} diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoopSystem.cs.meta b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoopSystem.cs.meta deleted file mode 100644 index bf2b85f2f2..0000000000 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoopSystem.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 812d7f0d8b55ccd44820717e1ae1e9b1 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateManager.cs b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateManager.cs deleted file mode 100644 index 0bb8e858e1..0000000000 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateManager.cs +++ /dev/null @@ -1,306 +0,0 @@ -/// About the Network Update Loop -/// The NetworkUpdateEngine is a temporary solution for the network update loop implementation. -/// This will be revised with a more robust and modular implementation in the near future. - -using System; -using System.Text; -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.PlayerLoop; -using UnityEngine.LowLevel; - -namespace MLAPI -{ - /// - /// NetworkUpdateManager - /// External public facing class for the registration of and processing of network updates - /// - public class NetworkUpdateManager - { - public enum NetworkUpdateStage - { - Default, //Will default to the UPDATE stage if no setting was made - PreUpdate, //Invoked after EarlyUpdate.UnityWebRequestUpdate - FixedUpdate, //Invoked after FixedUpdate.AudioFixedUpdate (prior to any physics being applied or simulated) - Update, //Invoked after PreUpdate.UpdateVideo (just before the primary Update is invoked) - LateUpdate //Invoked after PostLateUpdate.ProcessWebSendMessages (after all updates) - } - - private static Dictionary> s_RegisteredUpdateLoopSystems = new Dictionary>(); - - - /// - /// RegisterSystem - /// Registers all of the defined update stages - /// - /// - private static void RegisterSystem(Dictionary systems) - { - var def = PlayerLoop.GetCurrentPlayerLoop(); - - foreach (var updateStage in systems) - { - var InsertAfterType = typeof(EarlyUpdate.UnityWebRequestUpdate); - switch (updateStage.Key) - { - case NetworkUpdateStage.PreUpdate: - { - InsertAfterType = typeof(EarlyUpdate.UnityWebRequestUpdate); - break; - } - case NetworkUpdateStage.FixedUpdate: - { - InsertAfterType = typeof(FixedUpdate.AudioFixedUpdate); - break; - } - case NetworkUpdateStage.Update: - { - InsertAfterType = typeof(PreUpdate.UpdateVideo); - break; - } - case NetworkUpdateStage.LateUpdate: - { - InsertAfterType = typeof(PostLateUpdate.ProcessWebSendMessages); - break; - } - } - - InsertSystem(ref def, updateStage.Value, InsertAfterType); - } - -#if UNITY_EDITOR - PrintPlayerLoop(def); -#endif - - PlayerLoop.SetPlayerLoop(def); - } - - /// - /// OnNetworkLoopSystemDestroyed - /// This should be invoked by the registered INetworkUpdateLoopSystem when the class is being destroyed or it no longer wants to receive updates - /// - /// - private static void OnNetworkLoopSystemDestroyed(INetworkUpdateLoopSystem networkLoopSystem) - { - if (s_RegisteredUpdateLoopSystems.ContainsKey(networkLoopSystem)) - { - var def = PlayerLoop.GetCurrentPlayerLoop(); - foreach (KeyValuePair updateStage in s_RegisteredUpdateLoopSystems[networkLoopSystem]) - { - if (!RemoveSystem(ref def, updateStage.Value)) - { - Debug.LogWarning(updateStage.Value.type.Name + " tried to remove itself but no instsance was found!!!"); - } - } - - s_RegisteredUpdateLoopSystems.Remove(networkLoopSystem); -#if UNITY_EDITOR - PrintPlayerLoop(def); -#endif - PlayerLoop.SetPlayerLoop(def); - } - } - - /// - /// NetworkLoopRegistration - /// This will register any class that has an INetworkUpdateLoopSystem interface assignment - /// - /// class instace to register - public static void NetworkLoopRegistration(INetworkUpdateLoopSystem networkLoopSystem) - { - if (!s_RegisteredUpdateLoopSystems.ContainsKey(networkLoopSystem)) - { - Dictionary RegisterPlayerLoopSystems = new Dictionary(); - - foreach (NetworkUpdateStage stage in Enum.GetValues(typeof(NetworkUpdateStage))) - { - Action updateFunction = networkLoopSystem.RegisterUpdate(stage); - if (updateFunction != null) - { - PlayerLoopSystem.UpdateFunction callback = new PlayerLoopSystem.UpdateFunction(updateFunction); - PlayerLoopSystem stageLoop = new PlayerLoopSystem() { updateDelegate = callback, type = networkLoopSystem.GetType() }; - if (stageLoop.updateDelegate != null) - { - RegisterPlayerLoopSystems.Add(stage, stageLoop); - } - } - } - - if (RegisterPlayerLoopSystems.Count > 0) - { - //Keep track of which systems are registered. - s_RegisteredUpdateLoopSystems.Add(networkLoopSystem, RegisterPlayerLoopSystems); - - //Actually register all valid update stages for this system - RegisterSystem(RegisterPlayerLoopSystems); - - //Register the callback to be used when the system is removed/deleted/destroyed - networkLoopSystem.RegisterUpdateLoopSystemDestroyCallback(OnNetworkLoopSystemDestroyed); - } - } - } - - /// - /// RemoveSystem - /// Recursively search for the given system type and remove system - /// - /// - /// - /// - private static bool RemoveSystem(ref PlayerLoopSystem system, PlayerLoopSystem toRemove) - { - if (system.subSystemList == null) - { - return false; - } - - for (int i = 0; i < system.subSystemList.Length; ++i) - { - if (system.subSystemList[i].type == toRemove.type) - { - RemoveSystemAt(ref system, toRemove); - return true; - } - } - - for (var i = 0; i < system.subSystemList.Length; i++) - { - if (RemoveSystem(ref system.subSystemList[i], toRemove)) - { - return true; - } - } - - return false; - } - - /// - /// RemoveSystemAt - /// Copies the subSystemList of the given system, but excludes the specified PlayerLoopSystem from the list - /// - /// PlayerLoopSystem to be inserted into - /// PlayerLoopSystem to insert - private static void RemoveSystemAt(ref PlayerLoopSystem system, PlayerLoopSystem toRemove) - { - PlayerLoopSystem[] newSubSystems = new PlayerLoopSystem[system.subSystemList.Length - 1]; - for (int i = 0, newSystemIdx = 0; i < newSubSystems.Length - 1; ++i) - { - if (system.subSystemList[i].type != toRemove.type && system.subSystemList[i].updateFunction != toRemove.updateFunction) - { - newSubSystems[newSystemIdx++] = system.subSystemList[i]; - } - } - - system.subSystemList = newSubSystems; - } - - /// - /// InsertSystem - /// Recursively search for the given system type and insert the new system immediately afterwards - /// - /// PlayerLoopSystem to search - /// PlayerLoopSystem to insert - /// location to insert the PlayerLoopSystem - /// - private static bool InsertSystem(ref PlayerLoopSystem system, PlayerLoopSystem toInsert, Type insertAfter) - { - if (system.subSystemList == null) - { - return false; - } - - for (int i = 0; i < system.subSystemList.Length; ++i) - { - if (system.subSystemList[i].type == insertAfter) - { - InsertSystemAt(ref system, toInsert, i + 1); - return true; - } - } - - for (var i = 0; i < system.subSystemList.Length; i++) - { - if (InsertSystem(ref system.subSystemList[i], toInsert, insertAfter)) - { - return true; - } - } - - return false; - } - - /// - /// InsertSystemAt - /// Copies the subSystemList of the given system and inserts a new system at the given index - /// - /// PlayerLoopSystem to be inserted into - /// PlayerLoopSystem to insert - /// position to insert the PlayerLoopSystem - private static void InsertSystemAt(ref PlayerLoopSystem system, PlayerLoopSystem toInsert, int pos) - { - PlayerLoopSystem[] newSubSystems = new PlayerLoopSystem[system.subSystemList.Length + 1]; - for (int i = 0, oldSystemIdx = 0; i < newSubSystems.Length; ++i) - { - if (i == pos) - { - newSubSystems[i] = toInsert; - } - else - { - newSubSystems[i] = system.subSystemList[oldSystemIdx++]; - } - } - - system.subSystemList = newSubSystems; - } - -#if UNITY_EDITOR - /// - /// PrintPlayerLoop - /// Prints all PlayerLoopSystems within the PlayerLoopSystem provided - /// - /// PlayerLoopSystem - private static void PrintPlayerLoop(PlayerLoopSystem pl) - { - var sb = new StringBuilder(); - RecursivePlayerLoopPrint(pl, sb, 0); - Debug.Log(sb.ToString()); - } - - /// - /// RecursivePlayerLoopPrint - /// Recursively build the entire PlayerLoopSystem list - /// - /// PlayerLoopSystem to be added - /// StringBuilder to add to - /// Maximum recursion depth - private static void RecursivePlayerLoopPrint(PlayerLoopSystem def, StringBuilder sb, int depth) - { - if (depth == 0) - { - sb.AppendLine("ROOT NODE"); - } - else if (def.type != null) - { - for (int i = 0; i < depth; i++) - { - sb.Append("\t"); - } - - sb.AppendLine(def.type.Name); - } - - if (def.subSystemList != null) - { - depth++; - foreach (var s in def.subSystemList) - { - RecursivePlayerLoopPrint(s, sb, depth); - } - - depth--; - } - } -#endif - } -} \ No newline at end of file diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateManager.cs.meta b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateManager.cs.meta deleted file mode 100644 index da4e1b466f..0000000000 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateManager.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 09a23caab021bc84ba7a47e790456334 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkedBehaviour.cs b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkedBehaviour.cs index 6bf47c925e..40d19751be 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkedBehaviour.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkedBehaviour.cs @@ -74,11 +74,6 @@ public BitSerializer __beginSendServerRpc(ServerRpcParams serverRpcParams, RpcDe if (IsHost) { - if (serverRpcParams.Send.UpdateStage == NetworkUpdateManager.NetworkUpdateStage.Default) - { - serverRpcParams.Send.UpdateStage = NetworkUpdateManager.NetworkUpdateStage.Update; - } - writer = rpcQueueContainer.BeginAddQueueItemToFrame(RpcQueueContainer.QueueItemType.ServerRpc, Time.realtimeSinceStartup, transportChannel, 0, NetworkingManager.Singleton.ServerClientId, null, QueueHistoryFrame.QueueFrameType.Inbound, serverRpcParams.Send.UpdateStage); @@ -92,7 +87,7 @@ public BitSerializer __beginSendServerRpc(ServerRpcParams serverRpcParams, RpcDe else { writer = rpcQueueContainer.BeginAddQueueItemToFrame(RpcQueueContainer.QueueItemType.ServerRpc, Time.realtimeSinceStartup, transportChannel, 0, - NetworkingManager.Singleton.ServerClientId, null, QueueHistoryFrame.QueueFrameType.Outbound, NetworkUpdateManager.NetworkUpdateStage.LateUpdate); + NetworkingManager.Singleton.ServerClientId, null, QueueHistoryFrame.QueueFrameType.Outbound, NetworkUpdateStage.PostLateUpdate); if (!isUsingBatching) { writer.WriteBit(false); // Encrypted @@ -103,16 +98,7 @@ public BitSerializer __beginSendServerRpc(ServerRpcParams serverRpcParams, RpcDe writer.WriteUInt64Packed(NetworkId); // NetworkObjectId writer.WriteUInt16Packed(GetBehaviourId()); // NetworkBehaviourId - - //Write the update stage in front of RPC related information - if (serverRpcParams.Send.UpdateStage == NetworkUpdateManager.NetworkUpdateStage.Default) - { - writer.WriteUInt16Packed((ushort)NetworkUpdateManager.NetworkUpdateStage.Update); - } - else - { - writer.WriteUInt16Packed((ushort)serverRpcParams.Send.UpdateStage); - } + writer.WriteByte((byte)serverRpcParams.Send.UpdateStage); // NetworkUpdateStage return writer.Serializer; } @@ -132,13 +118,12 @@ public void __endSendServerRpc(BitSerializer serializer, ServerRpcParams serverR var rpcQueueContainer = NetworkingManager.Singleton.rpcQueueContainer; if (IsHost) { - rpcQueueContainer.EndAddQueueItemToFrame(serializer.Writer, QueueHistoryFrame.QueueFrameType.Inbound, serverRpcParams.Send.UpdateStage == NetworkUpdateManager.NetworkUpdateStage.Default ? NetworkUpdateManager.NetworkUpdateStage.Update:serverRpcParams.Send.UpdateStage ); + rpcQueueContainer.EndAddQueueItemToFrame(serializer.Writer, QueueHistoryFrame.QueueFrameType.Inbound, serverRpcParams.Send.UpdateStage); } else { - rpcQueueContainer.EndAddQueueItemToFrame(serializer.Writer, QueueHistoryFrame.QueueFrameType.Outbound, NetworkUpdateManager.NetworkUpdateStage.LateUpdate); + rpcQueueContainer.EndAddQueueItemToFrame(serializer.Writer, QueueHistoryFrame.QueueFrameType.Outbound, NetworkUpdateStage.PostLateUpdate); } - } [Browsable(false)] @@ -171,10 +156,6 @@ public BitSerializer __beginSendClientRpc(ClientRpcParams clientRpcParams, RpcDe var ContainsServerClientId = ClientIds.Contains(NetworkingManager.Singleton.ServerClientId); if (IsHost && ContainsServerClientId) { - if (clientRpcParams.Send.UpdateStage == NetworkUpdateManager.NetworkUpdateStage.Default) - { - clientRpcParams.Send.UpdateStage = NetworkUpdateManager.NetworkUpdateStage.Update; - } //Always write to the next frame's inbound queue writer = rpcQueueContainer.BeginAddQueueItemToFrame(RpcQueueContainer.QueueItemType.ClientRpc, Time.realtimeSinceStartup, transportChannel, 0, NetworkingManager.Singleton.ServerClientId, null, QueueHistoryFrame.QueueFrameType.Inbound, clientRpcParams.Send.UpdateStage); @@ -187,7 +168,7 @@ public BitSerializer __beginSendClientRpc(ClientRpcParams clientRpcParams, RpcDe //Switch to the outbound queue writer = rpcQueueContainer.BeginAddQueueItemToFrame(RpcQueueContainer.QueueItemType.ClientRpc, Time.realtimeSinceStartup, Channel.ReliableRPC, 0, NetworkId, - ClientIds, QueueHistoryFrame.QueueFrameType.Outbound, NetworkUpdateManager.NetworkUpdateStage.LateUpdate); + ClientIds, QueueHistoryFrame.QueueFrameType.Outbound, NetworkUpdateStage.PostLateUpdate); if (!isUsingBatching) { @@ -209,7 +190,7 @@ public BitSerializer __beginSendClientRpc(ClientRpcParams clientRpcParams, RpcDe else { writer = rpcQueueContainer.BeginAddQueueItemToFrame(RpcQueueContainer.QueueItemType.ClientRpc, Time.realtimeSinceStartup, transportChannel, 0, NetworkId, - ClientIds, QueueHistoryFrame.QueueFrameType.Outbound, NetworkUpdateManager.NetworkUpdateStage.LateUpdate); + ClientIds, QueueHistoryFrame.QueueFrameType.Outbound, NetworkUpdateStage.PostLateUpdate); if (!isUsingBatching) { @@ -221,16 +202,7 @@ public BitSerializer __beginSendClientRpc(ClientRpcParams clientRpcParams, RpcDe writer.WriteUInt64Packed(NetworkId); // NetworkObjectId writer.WriteUInt16Packed(GetBehaviourId()); // NetworkBehaviourId - - // Write the update stage in front of RPC related information - if (clientRpcParams.Send.UpdateStage == NetworkUpdateManager.NetworkUpdateStage.Default) - { - writer.WriteUInt16Packed((ushort)NetworkUpdateManager.NetworkUpdateStage.Update); - } - else - { - writer.WriteUInt16Packed((ushort)clientRpcParams.Send.UpdateStage); - } + writer.WriteByte((byte)clientRpcParams.Send.UpdateStage); // NetworkUpdateStage return writer.Serializer; } @@ -256,19 +228,16 @@ public void __endSendClientRpc(BitSerializer serializer, ClientRpcParams clientR { ClientIds = NetworkingManager.Singleton.ConnectedClientsList.Select(c => c.ClientId).ToArray(); } - var ContainsServerClientId = ClientIds.Contains(NetworkingManager.Singleton.ServerClientId); + var ContainsServerClientId = ClientIds.Contains(NetworkingManager.Singleton.ServerClientId); if (ContainsServerClientId && ClientIds.Length == 1) { - if (clientRpcParams.Send.UpdateStage == NetworkUpdateManager.NetworkUpdateStage.Default) - { - clientRpcParams.Send.UpdateStage = NetworkUpdateManager.NetworkUpdateStage.Update; - } rpcQueueContainer.EndAddQueueItemToFrame(serializer.Writer, QueueHistoryFrame.QueueFrameType.Inbound, clientRpcParams.Send.UpdateStage); return; } } - rpcQueueContainer.EndAddQueueItemToFrame(serializer.Writer, QueueHistoryFrame.QueueFrameType.Outbound, NetworkUpdateManager.NetworkUpdateStage.LateUpdate); + + rpcQueueContainer.EndAddQueueItemToFrame(serializer.Writer, QueueHistoryFrame.QueueFrameType.Outbound, NetworkUpdateStage.PostLateUpdate); } /// diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkingManager.cs b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkingManager.cs index b677cc9854..692bd98d22 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkingManager.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkingManager.cs @@ -35,7 +35,7 @@ namespace MLAPI /// The main component of the library /// [AddComponentMenu("MLAPI/NetworkingManager", -100)] - public class NetworkingManager : UpdateLoopBehaviour + public class NetworkingManager : MonoBehaviour, INetworkUpdateSystem { [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Never)] @@ -634,26 +634,41 @@ public void SetSingleton() OnSingletonReady(); } + private void Awake() + { + rpcQueueContainer = new RpcQueueContainer(false); + //Note: Since frame history is not being used, this is set to 0 + //To test frame history, increase the number to (n) where n > 0 + rpcQueueContainer.Initialize(0); + } + private void OnEnable() { if (Singleton != null && Singleton != this) { - Destroy(this.gameObject); - } - else - { - RegisterUpdateLoopSystem(); - SetSingleton(); - if (DontDestroy) - DontDestroyOnLoad(gameObject); - if (RunInBackground) - Application.runInBackground = true; + Destroy(gameObject); + return; } + + // Register INetworkUpdateSystem + this.RegisterNetworkUpdate(NetworkUpdateStage.EarlyUpdate); + this.RegisterNetworkUpdate(NetworkUpdateStage.PreUpdate); + + SetSingleton(); + if (DontDestroy) + DontDestroyOnLoad(gameObject); + if (RunInBackground) + Application.runInBackground = true; + } + + private void OnDisable() + { + // Unregister INetworkUpdateSystem + this.UnregisterAllNetworkUpdates(); } private void OnDestroy() { - OnNetworkLoopSystemRemove(); //NSS: This is ok to leave this check here rpcQueueContainer?.Shutdown(); @@ -686,42 +701,18 @@ public void Shutdown() } } - /// - /// InternalRegisterNetworkUpdateStage - /// Registers all pertinent update stages for NetworkingManager - /// - /// update stage to get callback for - /// - protected override Action InternalRegisterNetworkUpdateStage(NetworkUpdateManager.NetworkUpdateStage stage) + // INetworkUpdateSystem + public void NetworkUpdate(NetworkUpdateStage updateStage) { - Action updateStageCallback = null; - switch (stage) + switch (updateStage) { - case NetworkUpdateManager.NetworkUpdateStage.PreUpdate: - { - updateStageCallback = NetworkPreUpdate; - break; - } - case NetworkUpdateManager.NetworkUpdateStage.Update: - { - updateStageCallback = NetworkUpdate; - break; - } + case NetworkUpdateStage.EarlyUpdate: + OnNetworkEarlyUpdate(); + break; + case NetworkUpdateStage.PreUpdate: + OnNetworkPreUpdate(); + break; } - - return updateStageCallback; - } - - /// - /// Awake - /// Currently this only creates the RpcQueueContainer instance and initializes it. - /// - private void Awake() - { - rpcQueueContainer = new RpcQueueContainer(false); - //Note: Since frame history is not being used, this is set to 0 - //To test frame history, increase the number to (n) where n > 0 - rpcQueueContainer.Initialize(0); } private float m_LastReceiveTickTime; @@ -729,11 +720,7 @@ private void Awake() private float m_EventOvershootCounter; private float m_LastTimeSyncTime; - /// - /// NetworkPreUpdate: - /// Mostly for handling the receiving of RPCs - /// - private void NetworkPreUpdate() + private void OnNetworkEarlyUpdate() { if (IsListening) { @@ -774,11 +761,7 @@ private void NetworkPreUpdate() } } - /// - /// NetworkUpdate: - /// Primarily handles all remaining messages, network variable/behavior updates - /// - private void NetworkUpdate() + private void OnNetworkPreUpdate() { if (IsListening) { @@ -1253,7 +1236,7 @@ public static void InvokeRpc(RpcFrameQueueItem queueItem) #endif var networkObjectId = queueItem.streamReader.ReadUInt64Packed(); var networkBehaviourId = queueItem.streamReader.ReadUInt16Packed(); - var networkUpdateStage = queueItem.streamReader.ReadUInt16Packed(); + var networkUpdateStage = queueItem.streamReader.ReadByteDirect(); var networkMethodId = queueItem.streamReader.ReadUInt32Packed(); if (__ntable.ContainsKey(networkMethodId)) @@ -1272,7 +1255,7 @@ public static void InvokeRpc(RpcFrameQueueItem queueItem) { Receive = new ServerRpcReceiveParams { - UpdateStage = (NetworkUpdateManager.NetworkUpdateStage)networkUpdateStage, + UpdateStage = (NetworkUpdateStage)networkUpdateStage, SenderClientId = queueItem.networkId } }; @@ -1282,7 +1265,7 @@ public static void InvokeRpc(RpcFrameQueueItem queueItem) { Receive = new ClientRpcReceiveParams { - UpdateStage = (NetworkUpdateManager.NetworkUpdateStage)networkUpdateStage + UpdateStage = (NetworkUpdateStage)networkUpdateStage } }; break; diff --git a/com.unity.multiplayer.mlapi/Runtime/Messaging/RpcParams.cs b/com.unity.multiplayer.mlapi/Runtime/Messaging/RpcParams.cs index 466acd6353..e12b8a1a7a 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Messaging/RpcParams.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Messaging/RpcParams.cs @@ -4,12 +4,12 @@ namespace MLAPI.Messaging { public struct ServerRpcSendParams { - public NetworkUpdateManager.NetworkUpdateStage UpdateStage; + public NetworkUpdateStage UpdateStage; } public struct ServerRpcReceiveParams { - public NetworkUpdateManager.NetworkUpdateStage UpdateStage; + public NetworkUpdateStage UpdateStage; public ulong SenderClientId; } @@ -21,13 +21,13 @@ public struct ServerRpcParams public struct ClientRpcSendParams { - public NetworkUpdateManager.NetworkUpdateStage UpdateStage; + public NetworkUpdateStage UpdateStage; public ulong[] TargetClientIds; } public struct ClientRpcReceiveParams { - public NetworkUpdateManager.NetworkUpdateStage UpdateStage; + public NetworkUpdateStage UpdateStage; } public struct ClientRpcParams diff --git a/com.unity.multiplayer.mlapi/Runtime/Messaging/RpcQueue/QueueHistoryFrame.cs b/com.unity.multiplayer.mlapi/Runtime/Messaging/RpcQueue/QueueHistoryFrame.cs index 99ecd0bdd5..55b3673f97 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Messaging/RpcQueue/QueueHistoryFrame.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Messaging/RpcQueue/QueueHistoryFrame.cs @@ -34,7 +34,7 @@ public enum QueueFrameType private readonly QueueFrameType m_QueueFrameType; private int m_MaximumClients; private long m_CurrentStreamSizeMark; - private NetworkUpdateManager.NetworkUpdateStage m_StreamUpdateStage; //Update stage specific to RPCs (typically inbound has most potential for variation) + private NetworkUpdateStage m_StreamUpdateStage; //Update stage specific to RPCs (typically inbound has most potential for variation) private const int m_MaxStreamBounds = 131072; private const int m_MinStreamBounds = 0; @@ -244,7 +244,7 @@ public void CloseQueue() /// QueueHistoryFrame Constructor /// /// type of queue history frame (Inbound/Outbound) - public QueueHistoryFrame(QueueFrameType queueType, NetworkUpdateManager.NetworkUpdateStage updateStage, int maxClients = 512) + public QueueHistoryFrame(QueueFrameType queueType, NetworkUpdateStage updateStage, int maxClients = 512) { m_MaximumClients = maxClients; m_QueueFrameType = queueType; diff --git a/com.unity.multiplayer.mlapi/Runtime/Messaging/RpcQueue/RpcFrameQueueItem.cs b/com.unity.multiplayer.mlapi/Runtime/Messaging/RpcQueue/RpcFrameQueueItem.cs index 28ccec99f8..8fdfe27083 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Messaging/RpcQueue/RpcFrameQueueItem.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Messaging/RpcQueue/RpcFrameQueueItem.cs @@ -14,7 +14,7 @@ namespace MLAPI.Messaging /// public struct RpcFrameQueueItem { - public NetworkUpdateManager.NetworkUpdateStage updateStage; + public NetworkUpdateStage updateStage; public RpcQueueContainer.QueueItemType queueItemType; public SecuritySendFlags sendFlags; public ulong networkId; //Sender's network Identifier diff --git a/com.unity.multiplayer.mlapi/Runtime/Messaging/RpcQueue/RpcQueueContainer.cs b/com.unity.multiplayer.mlapi/Runtime/Messaging/RpcQueue/RpcQueueContainer.cs index 32cfeca200..359768c914 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Messaging/RpcQueue/RpcQueueContainer.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Messaging/RpcQueue/RpcQueueContainer.cs @@ -11,7 +11,7 @@ namespace MLAPI.Messaging /// RpcQueueContainer /// Handles the management of an Rpc Queue /// - public class RpcQueueContainer : GenericUpdateLoopSystem + public class RpcQueueContainer : INetworkUpdateSystem { private const int k_MinQueueHistory = 2; //We need a minimum of 2 queue history buffers in order to properly handle looping back Rpcs when a host @@ -31,10 +31,9 @@ public enum RpcQueueProcessingTypes Receive, } - //Inbound and Outbound QueueHistoryFrames - private readonly Dictionary>> QueueHistory = - new Dictionary>>(); - + // Inbound and Outbound QueueHistoryFrames + private readonly Dictionary>> QueueHistory = + new Dictionary>>(); private RpcQueueProcessor m_RpcQueueProcessor; @@ -57,77 +56,17 @@ public void EnableBatchedRpcs(bool isbatchingEnabled) m_IsNotUsingBatching = !isbatchingEnabled; } - /// - /// PreUpdateStage - /// Predefined internal network loop update system action - /// - void PreUpdateStage() + // INetworkUpdateSystem + public void NetworkUpdate(NetworkUpdateStage updateStage) { - ProcessAndFlushRPCQueue(RpcQueueContainer.RpcQueueProcessingTypes.Receive, NetworkUpdateManager.NetworkUpdateStage.PreUpdate); - } + ProcessAndFlushRPCQueue(RpcQueueProcessingTypes.Receive, updateStage); - /// - /// FixedUpdateStage - /// Predefined internal network loop update system action - /// - void FixedUpdateStage() - { - ProcessAndFlushRPCQueue(RpcQueueContainer.RpcQueueProcessingTypes.Receive, NetworkUpdateManager.NetworkUpdateStage.FixedUpdate); - } - - /// - /// UpdateStage - /// Predefined internal network loop update system action - /// - void UpdateStage() - { - ProcessAndFlushRPCQueue(RpcQueueContainer.RpcQueueProcessingTypes.Receive, NetworkUpdateManager.NetworkUpdateStage.Update); - } - - /// - /// LateUpdateStage - /// Predefined internal network loop update system action - /// - void LateUpdateStage() - { - ProcessAndFlushRPCQueue(RpcQueueContainer.RpcQueueProcessingTypes.Receive, NetworkUpdateManager.NetworkUpdateStage.LateUpdate); - ProcessAndFlushRPCQueue(RpcQueueContainer.RpcQueueProcessingTypes.Send, NetworkUpdateManager.NetworkUpdateStage.LateUpdate); - } - - protected override Action InternalRegisterNetworkUpdateStage(NetworkUpdateManager.NetworkUpdateStage stage) - { - Action updateStageAction = null; - if (!m_ProcessUpdateStagesExternally) + if (updateStage == NetworkUpdateStage.PostLateUpdate) { - switch (stage) - { - case NetworkUpdateManager.NetworkUpdateStage.PreUpdate: - { - updateStageAction = PreUpdateStage; - break; - } - case NetworkUpdateManager.NetworkUpdateStage.FixedUpdate: - { - updateStageAction = FixedUpdateStage; - break; - } - case NetworkUpdateManager.NetworkUpdateStage.Update: - { - updateStageAction = UpdateStage; - break; - } - case NetworkUpdateManager.NetworkUpdateStage.LateUpdate: - { - updateStageAction = LateUpdateStage; - break; - } - } + ProcessAndFlushRPCQueue(RpcQueueProcessingTypes.Send, updateStage); } - - return updateStageAction; } - /// /// GetStreamBufferFrameCount /// Returns how many frames have been processed (Inbound/Outbound) @@ -161,7 +100,7 @@ public void AddToInternalMLAPISendQueue(RpcFrameQueueItem queueItem) /// Will process the RPC queue and then move to the next available frame /// /// - public void ProcessAndFlushRPCQueue(RpcQueueProcessingTypes queueType, NetworkUpdateManager.NetworkUpdateStage currentUpdateStage) + public void ProcessAndFlushRPCQueue(RpcQueueProcessingTypes queueType, NetworkUpdateStage currentUpdateStage) { if (m_RpcQueueProcessor == null) { @@ -189,7 +128,7 @@ public void ProcessAndFlushRPCQueue(RpcQueueProcessingTypes queueType, NetworkUp /// /// /// QueueHistoryFrame - public QueueHistoryFrame GetCurrentFrame(QueueHistoryFrame.QueueFrameType qType, NetworkUpdateManager.NetworkUpdateStage currentUpdateStage) + public QueueHistoryFrame GetCurrentFrame(QueueHistoryFrame.QueueFrameType qType, NetworkUpdateStage currentUpdateStage) { if (QueueHistory.ContainsKey(qType)) { @@ -241,7 +180,7 @@ public void AdvanceFrameHistory(QueueHistoryFrame.QueueFrameType queueType) } - foreach (KeyValuePair queueHistoryByUpdates in QueueHistory[queueType][StreamBufferIndex]) + foreach (KeyValuePair queueHistoryByUpdates in QueueHistory[queueType][StreamBufferIndex]) { QueueHistoryFrame queueHistoryItem = queueHistoryByUpdates.Value; //This only gets reset when we advanced to next frame (do not reset this in the ResetQueueHistoryFrame) @@ -333,16 +272,10 @@ internal void AddQueueItemToInboundFrame(QueueItemType qItemType, float timeStam var shortValue = BR.ReadUInt16Packed(); // NetworkBehaviourId (temporary, we reset position just below) - ushort updateStageValue = BR.ReadUInt16Packed(); + var updateStage = (NetworkUpdateStage)BR.ReadByteDirect(); BR.Dispose(); BR = null; - NetworkUpdateManager.NetworkUpdateStage updateStage = NetworkUpdateManager.NetworkUpdateStage.Update; - if (System.Enum.IsDefined(typeof(NetworkUpdateManager.NetworkUpdateStage), (int)updateStageValue)) - { - updateStage = (NetworkUpdateManager.NetworkUpdateStage)updateStageValue; - } - message.Position = originalPosition; QueueHistoryFrame queueHistoryItem = GetQueueHistoryFrame(QueueHistoryFrame.QueueFrameType.Inbound, updateStage); queueHistoryItem.isDirty = true; @@ -374,13 +307,13 @@ internal void AddQueueItemToInboundFrame(QueueItemType qItemType, float timeStam /// Sets the next frame inbond buffer as the loopback queue history frame in the current frame's outbound buffer /// /// - public void SetLoopBackFrameItem(NetworkUpdateManager.NetworkUpdateStage updateStage) + public void SetLoopBackFrameItem(NetworkUpdateStage updateStage) { //Get the next frame's inbound queue history frame QueueHistoryFrame loopbackHistoryframe = GetQueueHistoryFrame(QueueHistoryFrame.QueueFrameType.Inbound,updateStage,true); //Get the current frame's outbound queue history frame - QueueHistoryFrame queueHistoryItem = GetQueueHistoryFrame(QueueHistoryFrame.QueueFrameType.Outbound,NetworkUpdateManager.NetworkUpdateStage.LateUpdate,false); + QueueHistoryFrame queueHistoryItem = GetQueueHistoryFrame(QueueHistoryFrame.QueueFrameType.Outbound, NetworkUpdateStage.PostLateUpdate, false); if (queueHistoryItem != null) { @@ -400,9 +333,9 @@ public void SetLoopBackFrameItem(NetworkUpdateManager.NetworkUpdateStage updateS /// /// /// - public QueueHistoryFrame GetLoopBackHistoryFrame( QueueHistoryFrame.QueueFrameType queueFrameType,NetworkUpdateManager.NetworkUpdateStage updateStage) + public QueueHistoryFrame GetLoopBackHistoryFrame(QueueHistoryFrame.QueueFrameType queueFrameType, NetworkUpdateStage updateStage) { - return GetQueueHistoryFrame(queueFrameType,updateStage,false); + return GetQueueHistoryFrame(queueFrameType, updateStage, false); } /// @@ -417,13 +350,9 @@ public QueueHistoryFrame GetLoopBackHistoryFrame( QueueHistoryFrame.QueueFrameTy /// who the rpc is being sent to /// public PooledBitWriter BeginAddQueueItemToFrame(QueueItemType qItemType, float timeStamp, Channel channel, ushort sendflags, ulong sourceNetworkId, ulong[] targetNetworkIds, - QueueHistoryFrame.QueueFrameType queueFrameType, NetworkUpdateManager.NetworkUpdateStage updateStage) + QueueHistoryFrame.QueueFrameType queueFrameType, NetworkUpdateStage updateStage) { - bool getNextFrame = false; - if (NetworkingManager.Singleton.IsHost && queueFrameType == QueueHistoryFrame.QueueFrameType.Inbound) - { - getNextFrame = true; - } + bool getNextFrame = NetworkingManager.Singleton.IsHost && queueFrameType == QueueHistoryFrame.QueueFrameType.Inbound; QueueHistoryFrame queueHistoryItem = GetQueueHistoryFrame(queueFrameType, updateStage, getNextFrame); queueHistoryItem.isDirty = true; @@ -502,13 +431,9 @@ public PooledBitWriter BeginAddQueueItemToFrame(QueueItemType qItemType, float t /// We store final MSG size and track the total current frame queue size /// /// writer that was used - public void EndAddQueueItemToFrame(BitWriter writer, QueueHistoryFrame.QueueFrameType queueFrameType, NetworkUpdateManager.NetworkUpdateStage updateStage) + public void EndAddQueueItemToFrame(BitWriter writer, QueueHistoryFrame.QueueFrameType queueFrameType, NetworkUpdateStage updateStage) { - bool getNextFrame = false; - if (NetworkingManager.Singleton.IsHost && queueFrameType == QueueHistoryFrame.QueueFrameType.Inbound) - { - getNextFrame = true; - } + bool getNextFrame = NetworkingManager.Singleton.IsHost && queueFrameType == QueueHistoryFrame.QueueFrameType.Inbound; QueueHistoryFrame queueHistoryItem = GetQueueHistoryFrame(queueFrameType, updateStage, getNextFrame); QueueHistoryFrame loopBackHistoryFrame = queueHistoryItem.loopbackHistoryFrame; @@ -610,7 +535,7 @@ public void EndAddQueueItemToFrame(BitWriter writer, QueueHistoryFrame.QueueFram /// /// inbound or outbound /// QueueHistoryFrame or null - public QueueHistoryFrame GetQueueHistoryFrame(QueueHistoryFrame.QueueFrameType frameType, NetworkUpdateManager.NetworkUpdateStage updateStage, bool getNextFrame = false) + public QueueHistoryFrame GetQueueHistoryFrame(QueueHistoryFrame.QueueFrameType frameType, NetworkUpdateStage updateStage, bool getNextFrame = false) { int StreamBufferIndex = GetStreamBufferIndex(frameType); @@ -657,20 +582,20 @@ public void LoopbackSendFrame() //If we do not have loop back or testing mode enabled then ignore the call if (m_IsTestingEnabled) { - QueueHistoryFrame queueHistoryItemOutbound = GetQueueHistoryFrame(QueueHistoryFrame.QueueFrameType.Outbound, NetworkUpdateManager.NetworkUpdateStage.LateUpdate); + QueueHistoryFrame queueHistoryItemOutbound = GetQueueHistoryFrame(QueueHistoryFrame.QueueFrameType.Outbound, NetworkUpdateStage.PostLateUpdate); if (queueHistoryItemOutbound.queueItemOffsets.Count > 0) { //Reset inbound queues based on update stage - foreach (NetworkUpdateManager.NetworkUpdateStage stage in System.Enum.GetValues(typeof(NetworkUpdateManager.NetworkUpdateStage))) + foreach (NetworkUpdateStage netUpdateStage in Enum.GetValues(typeof(NetworkUpdateStage))) { - QueueHistoryFrame queueHistoryItemInbound = GetQueueHistoryFrame(QueueHistoryFrame.QueueFrameType.Inbound, stage); + QueueHistoryFrame queueHistoryItemInbound = GetQueueHistoryFrame(QueueHistoryFrame.QueueFrameType.Inbound, netUpdateStage); ResetQueueHistoryFrame(queueHistoryItemInbound); } PooledBitStream pooledBitStream = PooledBitStream.Get(); RpcFrameQueueItem rpcFrameQueueItem = queueHistoryItemOutbound.GetFirstQueueItem(); - while (rpcFrameQueueItem.queueItemType != RpcQueueContainer.QueueItemType.None) + while (rpcFrameQueueItem.queueItemType != QueueItemType.None) { pooledBitStream.SetLength(rpcFrameQueueItem.streamSize); pooledBitStream.Position = 0; @@ -706,20 +631,20 @@ public void Initialize(uint maxFrameHistory) if (!QueueHistory.ContainsKey(QueueHistoryFrame.QueueFrameType.Inbound)) { - QueueHistory.Add(QueueHistoryFrame.QueueFrameType.Inbound, new Dictionary>()); + QueueHistory.Add(QueueHistoryFrame.QueueFrameType.Inbound, new Dictionary>()); } if (!QueueHistory.ContainsKey(QueueHistoryFrame.QueueFrameType.Outbound)) { - QueueHistory.Add(QueueHistoryFrame.QueueFrameType.Outbound, new Dictionary>()); + QueueHistory.Add(QueueHistoryFrame.QueueFrameType.Outbound, new Dictionary>()); } for (int i = 0; i < m_MaxFrameHistory; i++) { if (!QueueHistory[QueueHistoryFrame.QueueFrameType.Outbound].ContainsKey(i)) { - QueueHistory[QueueHistoryFrame.QueueFrameType.Outbound].Add(i, new Dictionary()); - QueueHistoryFrame queueHistoryFrame = new QueueHistoryFrame(QueueHistoryFrame.QueueFrameType.Outbound, NetworkUpdateManager.NetworkUpdateStage.LateUpdate); + QueueHistory[QueueHistoryFrame.QueueFrameType.Outbound].Add(i, new Dictionary()); + var queueHistoryFrame = new QueueHistoryFrame(QueueHistoryFrame.QueueFrameType.Outbound, NetworkUpdateStage.PostLateUpdate); queueHistoryFrame.queueStream = PooledBitStream.Get(); queueHistoryFrame.queueStream.Position = 0; queueHistoryFrame.queueWriter = PooledBitWriter.Get(queueHistoryFrame.queueStream); @@ -727,23 +652,23 @@ public void Initialize(uint maxFrameHistory) queueHistoryFrame.queueItemOffsets = new List(); //For now all outbound, we will always have a single update in which they are processed (LATEUPDATE) - QueueHistory[QueueHistoryFrame.QueueFrameType.Outbound][i].Add(NetworkUpdateManager.NetworkUpdateStage.LateUpdate, queueHistoryFrame); + QueueHistory[QueueHistoryFrame.QueueFrameType.Outbound][i].Add(NetworkUpdateStage.PostLateUpdate, queueHistoryFrame); } if (!QueueHistory[QueueHistoryFrame.QueueFrameType.Inbound].ContainsKey(i)) { - QueueHistory[QueueHistoryFrame.QueueFrameType.Inbound].Add(i, new Dictionary()); + QueueHistory[QueueHistoryFrame.QueueFrameType.Inbound].Add(i, new Dictionary()); //For inbound, we create a queue history frame per update stage - foreach (NetworkUpdateManager.NetworkUpdateStage stage in Enum.GetValues(typeof(NetworkUpdateManager.NetworkUpdateStage))) + foreach (NetworkUpdateStage netUpdateStage in Enum.GetValues(typeof(NetworkUpdateStage))) { - QueueHistoryFrame queueHistoryFrame = new QueueHistoryFrame(QueueHistoryFrame.QueueFrameType.Inbound, stage); + QueueHistoryFrame queueHistoryFrame = new QueueHistoryFrame(QueueHistoryFrame.QueueFrameType.Inbound, netUpdateStage); queueHistoryFrame.queueStream = PooledBitStream.Get(); queueHistoryFrame.queueStream.Position = 0; queueHistoryFrame.queueWriter = PooledBitWriter.Get(queueHistoryFrame.queueStream); queueHistoryFrame.queueReader = PooledBitReader.Get(queueHistoryFrame.queueStream); queueHistoryFrame.queueItemOffsets = new List(); - QueueHistory[QueueHistoryFrame.QueueFrameType.Inbound][i].Add(stage, queueHistoryFrame); + QueueHistory[QueueHistoryFrame.QueueFrameType.Inbound][i].Add(netUpdateStage, queueHistoryFrame); } } } @@ -752,7 +677,7 @@ public void Initialize(uint maxFrameHistory) if (!m_ProcessUpdateStagesExternally) { //Register with the network update loop system - RegisterUpdateLoopSystem(); + this.RegisterAllNetworkUpdates(); } } @@ -792,15 +717,15 @@ public void Shutdown() if (!m_ProcessUpdateStagesExternally) { //Remove ourself from the network loop update system - OnNetworkLoopSystemRemove(); + this.UnregisterAllNetworkUpdates(); } //Dispose of any readers and writers - foreach (KeyValuePair>> queueHistorySection in QueueHistory) + foreach (KeyValuePair>> queueHistorySection in QueueHistory) { - foreach (KeyValuePair> queueHistoryItemByStage in queueHistorySection.Value) + foreach (KeyValuePair> queueHistoryItemByStage in queueHistorySection.Value) { - foreach (KeyValuePair queueHistoryItem in queueHistoryItemByStage.Value) + foreach (KeyValuePair queueHistoryItem in queueHistoryItemByStage.Value) { queueHistoryItem.Value.queueWriter?.Dispose(); queueHistoryItem.Value.queueReader?.Dispose(); diff --git a/com.unity.multiplayer.mlapi/Runtime/Messaging/RpcQueue/RpcQueueProcessor.cs b/com.unity.multiplayer.mlapi/Runtime/Messaging/RpcQueue/RpcQueueProcessor.cs index 2f96845734..154a120064 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Messaging/RpcQueue/RpcQueueProcessor.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Messaging/RpcQueue/RpcQueueProcessor.cs @@ -32,7 +32,7 @@ internal class RpcQueueProcessor /// ProcessReceiveQueue /// Public facing interface method to start processing all RPCs in the current inbound frame /// - public void ProcessReceiveQueue(NetworkUpdateManager.NetworkUpdateStage currentStage) + public void ProcessReceiveQueue(NetworkUpdateStage currentStage) { bool AdvanceFrameHistory = false; var rpcQueueContainer = NetworkingManager.Singleton.rpcQueueContainer; @@ -41,8 +41,8 @@ public void ProcessReceiveQueue(NetworkUpdateManager.NetworkUpdateStage currentS #if DEVELOPMENT_BUILD || UNITY_EDITOR s_MLAPIRPCQueueProcess.Begin(); #endif - var CurrentFrame = rpcQueueContainer.GetQueueHistoryFrame(QueueHistoryFrame.QueueFrameType.Inbound,currentStage); - var NextFrame = rpcQueueContainer.GetQueueHistoryFrame(QueueHistoryFrame.QueueFrameType.Inbound,currentStage,true); + var CurrentFrame = rpcQueueContainer.GetQueueHistoryFrame(QueueHistoryFrame.QueueFrameType.Inbound, currentStage); + var NextFrame = rpcQueueContainer.GetQueueHistoryFrame(QueueHistoryFrame.QueueFrameType.Inbound, currentStage, true); if (NextFrame.isDirty && NextFrame.hasLoopbackData) { AdvanceFrameHistory = true; @@ -161,7 +161,7 @@ private void RPCQueueSendAndFlush() var rpcQueueContainer = NetworkingManager.Singleton.rpcQueueContainer; if (rpcQueueContainer != null) { - var CurrentFrame = rpcQueueContainer.GetCurrentFrame(QueueHistoryFrame.QueueFrameType.Outbound,NetworkUpdateManager.NetworkUpdateStage.LateUpdate); + var CurrentFrame = rpcQueueContainer.GetCurrentFrame(QueueHistoryFrame.QueueFrameType.Outbound, NetworkUpdateStage.PostLateUpdate); if (CurrentFrame != null) { diff --git a/com.unity.multiplayer.mlapi/Runtime/Spawning/SpawnManager.cs b/com.unity.multiplayer.mlapi/Runtime/Spawning/SpawnManager.cs index 4065ad00a4..f136c01142 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Spawning/SpawnManager.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Spawning/SpawnManager.cs @@ -419,7 +419,7 @@ internal static void SendSpawnCallForObject(ulong clientId, NetworkedObject netO var queueItem = new RpcFrameQueueItem { - updateStage = NetworkUpdateManager.NetworkUpdateStage.Update, + updateStage = NetworkUpdateStage.Update, queueItemType = RpcQueueContainer.QueueItemType.CreateObject, networkId = 0, itemStream = stream, @@ -693,6 +693,7 @@ internal static void OnDestroyObject(ulong networkId, bool destroyGameObject) var queueItem = new RpcFrameQueueItem { + updateStage = NetworkUpdateStage.PostLateUpdate, queueItemType = RpcQueueContainer.QueueItemType.DestroyObject, networkId = networkId, itemStream = stream, From d4d6b3f6e25d5fee547cf7e566bceb39802e14d3 Mon Sep 17 00:00:00 2001 From: "M. Fatih MAR" Date: Tue, 16 Feb 2021 14:17:15 +0000 Subject: [PATCH 10/14] replace WaitForEndOfFrame with WaitUntil in tests --- .../Tests/Runtime/NetworkUpdateLoopTests.cs | 44 +++++++++---------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkUpdateLoopTests.cs b/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkUpdateLoopTests.cs index 4778902037..47a6e67b11 100644 --- a/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkUpdateLoopTests.cs +++ b/com.unity.multiplayer.mlapi/Tests/Runtime/NetworkUpdateLoopTests.cs @@ -75,9 +75,7 @@ public IEnumerator UpdateStagesPlain() const int kNetPostLateUpdateIndex = 6; int[] netUpdates = new int[7]; - yield return new WaitForEndOfFrame(); bool isTesting = false; - using (var plainScript = new MyPlainScript()) { plainScript.UpdateCallbacks = new NetworkUpdateCallbacks @@ -134,20 +132,21 @@ public IEnumerator UpdateStagesPlain() }; plainScript.Initialize(); - yield return new WaitForEndOfFrame(); + int nextFrameNumber = Time.frameCount + 1; + yield return new WaitUntil(() => Time.frameCount >= nextFrameNumber); isTesting = true; - for (int i = 0; i < 16; i++) - { - Assert.AreEqual(0, netUpdates[kNetInitializationIndex]); - Assert.AreEqual(i, netUpdates[kNetEarlyUpdateIndex]); - Assert.AreEqual(0, netUpdates[kNetFixedUpdateIndex]); - Assert.AreEqual(0, netUpdates[kNetPreUpdateIndex]); - Assert.AreEqual(0, netUpdates[kNetUpdateIndex]); - Assert.AreEqual(i, netUpdates[kNetPreLateUpdateIndex]); - Assert.AreEqual(0, netUpdates[kNetPostLateUpdateIndex]); - yield return new WaitForEndOfFrame(); - } + const int kRunTotalFrames = 16; + int waitFrameNumber = Time.frameCount + kRunTotalFrames; + yield return new WaitUntil(() => Time.frameCount >= waitFrameNumber); + + Assert.AreEqual(0, netUpdates[kNetInitializationIndex]); + Assert.AreEqual(kRunTotalFrames, netUpdates[kNetEarlyUpdateIndex]); + Assert.AreEqual(0, netUpdates[kNetFixedUpdateIndex]); + Assert.AreEqual(0, netUpdates[kNetPreUpdateIndex]); + Assert.AreEqual(0, netUpdates[kNetUpdateIndex]); + Assert.AreEqual(kRunTotalFrames, netUpdates[kNetPreLateUpdateIndex]); + Assert.AreEqual(0, netUpdates[kNetPostLateUpdateIndex]); } } @@ -219,9 +218,7 @@ public IEnumerator UpdateStagesMixed() const int kMonoLateUpdateIndex = 2; int[] monoUpdates = new int[3]; - yield return new WaitForEndOfFrame(); bool isTesting = false; - { var gameObject = new GameObject($"{nameof(NetworkUpdateLoopTests)}.{nameof(UpdateStagesMixed)} (Dummy)"); var gameScript = gameObject.AddComponent(); @@ -280,15 +277,16 @@ public IEnumerator UpdateStagesMixed() } }; - yield return new WaitForEndOfFrame(); + int nextFrameNumber = Time.frameCount + 1; + yield return new WaitUntil(() => Time.frameCount >= nextFrameNumber); isTesting = true; - for (int i = 0; i < 16; i++) - { - Assert.AreEqual(i, netUpdates[kNetPreUpdateIndex]); - Assert.AreEqual(netUpdates[kNetPreUpdateIndex], monoUpdates[kMonoUpdateIndex]); - yield return new WaitForEndOfFrame(); - } + const int kRunTotalFrames = 16; + int waitFrameNumber = Time.frameCount + kRunTotalFrames; + yield return new WaitUntil(() => Time.frameCount >= waitFrameNumber); + + Assert.AreEqual(kRunTotalFrames, netUpdates[kNetPreUpdateIndex]); + Assert.AreEqual(netUpdates[kNetPreUpdateIndex], monoUpdates[kMonoUpdateIndex]); GameObject.DestroyImmediate(gameObject); } From f82542c906dc4194ee66a887e24ff1f4a7ddcfcd Mon Sep 17 00:00:00 2001 From: "M. Fatih MAR" Date: Wed, 17 Feb 2021 07:05:40 +0000 Subject: [PATCH 11/14] comment 'default' for NetworkUpdateStage.Update enum value --- com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs index 3354a0158c..01e8d54aee 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs @@ -23,7 +23,7 @@ public enum NetworkUpdateStage : byte EarlyUpdate = 2, FixedUpdate = 3, PreUpdate = 4, - Update = 0, + Update = 0, // Default PreLateUpdate = 5, PostLateUpdate = 6 } From b50b31a4c8ee570630e56d6878e17f9d5d59b7e7 Mon Sep 17 00:00:00 2001 From: "M. Fatih MAR" Date: Wed, 17 Feb 2021 20:12:44 +0000 Subject: [PATCH 12/14] optimization & refactoring pass --- .../Runtime/Core/NetworkUpdateLoop.cs | 387 +++++------------- 1 file changed, 95 insertions(+), 292 deletions(-) diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs index 01e8d54aee..396e654e34 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System; +using System.Linq; using System.Collections.Generic; using UnityEngine; using UnityEngine.LowLevel; @@ -154,6 +155,92 @@ private static void Initialize() PlayerLoop.SetPlayerLoop(customPlayerLoop); } + /// + /// The current network update stage being executed. + /// + public static NetworkUpdateStage UpdateStage; + + /// + /// Registers a network update system to be executed in all network update stages. + /// + public static void RegisterAllNetworkUpdates(this INetworkUpdateSystem updateSystem) + { + foreach (NetworkUpdateStage updateStage in Enum.GetValues(typeof(NetworkUpdateStage))) + { + RegisterNetworkUpdate(updateSystem, updateStage); + } + } + + /// + /// Registers a network update system to be executed in a specific network update stage. + /// + public static void RegisterNetworkUpdate(this INetworkUpdateSystem updateSystem, NetworkUpdateStage updateStage = NetworkUpdateStage.Update) + { + int updateStageIndex = (int)updateStage; + if (!m_UpdateSystem_Sets[updateStageIndex].Contains(updateSystem)) + { + m_UpdateSystem_Sets[updateStageIndex].Add(updateSystem); + m_UpdateSystem_Arrays[updateStageIndex] = m_UpdateSystem_Sets[updateStageIndex].ToArray(); + } + } + + /// + /// Unregisters a network update system from all network update stages. + /// + public static void UnregisterAllNetworkUpdates(this INetworkUpdateSystem updateSystem) + { + foreach (NetworkUpdateStage updateStage in Enum.GetValues(typeof(NetworkUpdateStage))) + { + UnregisterNetworkUpdate(updateSystem, updateStage); + } + } + + /// + /// Unregisters a network update system from a specific network update stage. + /// + public static void UnregisterNetworkUpdate(this INetworkUpdateSystem updateSystem, NetworkUpdateStage updateStage = NetworkUpdateStage.Update) + { + int updateStageIndex = (int)updateStage; + if (m_UpdateSystem_Sets[updateStageIndex].Contains(updateSystem)) + { + m_UpdateSystem_Sets[updateStageIndex].Remove(updateSystem); + m_UpdateSystem_Arrays[updateStageIndex] = m_UpdateSystem_Sets[updateStageIndex].ToArray(); + } + } + + private static readonly HashSet[] m_UpdateSystem_Sets = + { + new HashSet(), // 0: Update + new HashSet(), // 1: Initialization + new HashSet(), // 2: EarlyUpdate + new HashSet(), // 3: FixedUpdate + new HashSet(), // 4: PreUpdate + new HashSet(), // 5: PreLateUpdate + new HashSet(), // 6: PostLateUpdate + }; + + private static readonly INetworkUpdateSystem[][] m_UpdateSystem_Arrays = + { + new INetworkUpdateSystem[0], // 0: Update + new INetworkUpdateSystem[0], // 1: Initialization + new INetworkUpdateSystem[0], // 2: EarlyUpdate + new INetworkUpdateSystem[0], // 3: FixedUpdate + new INetworkUpdateSystem[0], // 4: PreUpdate + new INetworkUpdateSystem[0], // 5: PreLateUpdate + new INetworkUpdateSystem[0], // 6: PostLateUpdate + }; + + private static void RunNetworkUpdateStage(NetworkUpdateStage updateStage) + { + UpdateStage = updateStage; + int updateStageIndex = (int)updateStage; + int arrayLength = m_UpdateSystem_Arrays[updateStageIndex].Length; + for (int i = 0; i < arrayLength; i++) + { + m_UpdateSystem_Arrays[updateStageIndex][i].NetworkUpdate(updateStage); + } + } + private struct NetworkInitialization { public static PlayerLoopSystem CreateLoopSystem() @@ -161,7 +248,7 @@ public static PlayerLoopSystem CreateLoopSystem() return new PlayerLoopSystem { type = typeof(NetworkInitialization), - updateDelegate = RunNetworkInitialization + updateDelegate = () => RunNetworkUpdateStage(NetworkUpdateStage.Initialization) }; } } @@ -173,7 +260,7 @@ public static PlayerLoopSystem CreateLoopSystem() return new PlayerLoopSystem { type = typeof(NetworkEarlyUpdate), - updateDelegate = RunNetworkEarlyUpdate + updateDelegate = () => RunNetworkUpdateStage(NetworkUpdateStage.EarlyUpdate) }; } } @@ -185,7 +272,7 @@ public static PlayerLoopSystem CreateLoopSystem() return new PlayerLoopSystem { type = typeof(NetworkFixedUpdate), - updateDelegate = RunNetworkFixedUpdate + updateDelegate = () => RunNetworkUpdateStage(NetworkUpdateStage.FixedUpdate) }; } } @@ -197,7 +284,7 @@ public static PlayerLoopSystem CreateLoopSystem() return new PlayerLoopSystem { type = typeof(NetworkPreUpdate), - updateDelegate = RunNetworkPreUpdate + updateDelegate = () => RunNetworkUpdateStage(NetworkUpdateStage.PreUpdate) }; } } @@ -209,7 +296,7 @@ public static PlayerLoopSystem CreateLoopSystem() return new PlayerLoopSystem { type = typeof(NetworkUpdate), - updateDelegate = RunNetworkUpdate + updateDelegate = () => RunNetworkUpdateStage(NetworkUpdateStage.Update) }; } } @@ -221,7 +308,7 @@ public static PlayerLoopSystem CreateLoopSystem() return new PlayerLoopSystem { type = typeof(NetworkPreLateUpdate), - updateDelegate = RunNetworkPreLateUpdate + updateDelegate = () => RunNetworkUpdateStage(NetworkUpdateStage.PreLateUpdate) }; } } @@ -233,293 +320,9 @@ public static PlayerLoopSystem CreateLoopSystem() return new PlayerLoopSystem { type = typeof(NetworkPostLateUpdate), - updateDelegate = RunNetworkPostLateUpdate + updateDelegate = () => RunNetworkUpdateStage(NetworkUpdateStage.PostLateUpdate) }; } } - - /// - /// Registers a network update system to be executed in all network update stages. - /// - public static void RegisterAllNetworkUpdates(this INetworkUpdateSystem updateSystem) - { - RegisterNetworkUpdate(updateSystem, NetworkUpdateStage.Initialization); - RegisterNetworkUpdate(updateSystem, NetworkUpdateStage.EarlyUpdate); - RegisterNetworkUpdate(updateSystem, NetworkUpdateStage.FixedUpdate); - RegisterNetworkUpdate(updateSystem, NetworkUpdateStage.PreUpdate); - RegisterNetworkUpdate(updateSystem, NetworkUpdateStage.Update); - RegisterNetworkUpdate(updateSystem, NetworkUpdateStage.PreLateUpdate); - RegisterNetworkUpdate(updateSystem, NetworkUpdateStage.PostLateUpdate); - } - - /// - /// Registers a network update system to be executed in a specific network update stage. - /// - public static void RegisterNetworkUpdate(this INetworkUpdateSystem updateSystem, NetworkUpdateStage updateStage = NetworkUpdateStage.Update) - { - switch (updateStage) - { - case NetworkUpdateStage.Initialization: - { - if (!m_Initialization_List.Contains(updateSystem)) - { - m_Initialization_List.Add(updateSystem); - m_Initialization_Array = m_Initialization_List.ToArray(); - } - - break; - } - case NetworkUpdateStage.EarlyUpdate: - { - if (!m_EarlyUpdate_List.Contains(updateSystem)) - { - m_EarlyUpdate_List.Add(updateSystem); - m_EarlyUpdate_Array = m_EarlyUpdate_List.ToArray(); - } - - break; - } - case NetworkUpdateStage.FixedUpdate: - { - if (!m_FixedUpdate_List.Contains(updateSystem)) - { - m_FixedUpdate_List.Add(updateSystem); - m_FixedUpdate_Array = m_FixedUpdate_List.ToArray(); - } - - break; - } - case NetworkUpdateStage.PreUpdate: - { - if (!m_PreUpdate_List.Contains(updateSystem)) - { - m_PreUpdate_List.Add(updateSystem); - m_PreUpdate_Array = m_PreUpdate_List.ToArray(); - } - - break; - } - case NetworkUpdateStage.Update: - { - if (!m_Update_List.Contains(updateSystem)) - { - m_Update_List.Add(updateSystem); - m_Update_Array = m_Update_List.ToArray(); - } - - break; - } - case NetworkUpdateStage.PreLateUpdate: - { - if (!m_PreLateUpdate_List.Contains(updateSystem)) - { - m_PreLateUpdate_List.Add(updateSystem); - m_PreLateUpdate_Array = m_PreLateUpdate_List.ToArray(); - } - - break; - } - case NetworkUpdateStage.PostLateUpdate: - { - if (!m_PostLateUpdate_List.Contains(updateSystem)) - { - m_PostLateUpdate_List.Add(updateSystem); - m_PostLateUpdate_Array = m_PostLateUpdate_List.ToArray(); - } - - break; - } - } - } - - /// - /// Unregisters a network update system from all network update stages. - /// - public static void UnregisterAllNetworkUpdates(this INetworkUpdateSystem updateSystem) - { - UnregisterNetworkUpdate(updateSystem, NetworkUpdateStage.Initialization); - UnregisterNetworkUpdate(updateSystem, NetworkUpdateStage.EarlyUpdate); - UnregisterNetworkUpdate(updateSystem, NetworkUpdateStage.FixedUpdate); - UnregisterNetworkUpdate(updateSystem, NetworkUpdateStage.PreUpdate); - UnregisterNetworkUpdate(updateSystem, NetworkUpdateStage.Update); - UnregisterNetworkUpdate(updateSystem, NetworkUpdateStage.PreLateUpdate); - UnregisterNetworkUpdate(updateSystem, NetworkUpdateStage.PostLateUpdate); - } - - /// - /// Unregisters a network update system from a specific network update stage. - /// - public static void UnregisterNetworkUpdate(this INetworkUpdateSystem updateSystem, NetworkUpdateStage updateStage = NetworkUpdateStage.Update) - { - switch (updateStage) - { - case NetworkUpdateStage.Initialization: - { - if (m_Initialization_List.Contains(updateSystem)) - { - m_Initialization_List.Remove(updateSystem); - m_Initialization_Array = m_Initialization_List.ToArray(); - } - - break; - } - case NetworkUpdateStage.EarlyUpdate: - { - if (m_EarlyUpdate_List.Contains(updateSystem)) - { - m_EarlyUpdate_List.Remove(updateSystem); - m_EarlyUpdate_Array = m_EarlyUpdate_List.ToArray(); - } - - break; - } - case NetworkUpdateStage.FixedUpdate: - { - if (m_FixedUpdate_List.Contains(updateSystem)) - { - m_FixedUpdate_List.Remove(updateSystem); - m_FixedUpdate_Array = m_FixedUpdate_List.ToArray(); - } - - break; - } - case NetworkUpdateStage.PreUpdate: - { - if (m_PreUpdate_List.Contains(updateSystem)) - { - m_PreUpdate_List.Remove(updateSystem); - m_PreUpdate_Array = m_PreUpdate_List.ToArray(); - } - - break; - } - case NetworkUpdateStage.Update: - { - if (m_Update_List.Contains(updateSystem)) - { - m_Update_List.Remove(updateSystem); - m_Update_Array = m_Update_List.ToArray(); - } - - break; - } - case NetworkUpdateStage.PreLateUpdate: - { - if (m_PreLateUpdate_List.Contains(updateSystem)) - { - m_PreLateUpdate_List.Remove(updateSystem); - m_PreLateUpdate_Array = m_PreLateUpdate_List.ToArray(); - } - - break; - } - case NetworkUpdateStage.PostLateUpdate: - { - if (m_PostLateUpdate_List.Contains(updateSystem)) - { - m_PostLateUpdate_List.Remove(updateSystem); - m_PostLateUpdate_Array = m_PostLateUpdate_List.ToArray(); - } - - break; - } - } - } - - /// - /// The current network update stage being executed. - /// - public static NetworkUpdateStage UpdateStage; - - private static readonly List m_Initialization_List = new List(); - private static INetworkUpdateSystem[] m_Initialization_Array = new INetworkUpdateSystem[0]; - - private static void RunNetworkInitialization() - { - UpdateStage = NetworkUpdateStage.Initialization; - int arrayLength = m_Initialization_Array.Length; - for (int i = 0; i < arrayLength; i++) - { - m_Initialization_Array[i].NetworkUpdate(UpdateStage); - } - } - - private static readonly List m_EarlyUpdate_List = new List(); - private static INetworkUpdateSystem[] m_EarlyUpdate_Array = new INetworkUpdateSystem[0]; - - private static void RunNetworkEarlyUpdate() - { - UpdateStage = NetworkUpdateStage.EarlyUpdate; - int arrayLength = m_EarlyUpdate_Array.Length; - for (int i = 0; i < arrayLength; i++) - { - m_EarlyUpdate_Array[i].NetworkUpdate(UpdateStage); - } - } - - private static readonly List m_FixedUpdate_List = new List(); - private static INetworkUpdateSystem[] m_FixedUpdate_Array = new INetworkUpdateSystem[0]; - - private static void RunNetworkFixedUpdate() - { - UpdateStage = NetworkUpdateStage.FixedUpdate; - int arrayLength = m_FixedUpdate_Array.Length; - for (int i = 0; i < arrayLength; i++) - { - m_FixedUpdate_Array[i].NetworkUpdate(UpdateStage); - } - } - - private static readonly List m_PreUpdate_List = new List(); - private static INetworkUpdateSystem[] m_PreUpdate_Array = new INetworkUpdateSystem[0]; - - private static void RunNetworkPreUpdate() - { - UpdateStage = NetworkUpdateStage.PreUpdate; - int arrayLength = m_PreUpdate_Array.Length; - for (int i = 0; i < arrayLength; i++) - { - m_PreUpdate_Array[i].NetworkUpdate(UpdateStage); - } - } - - private static readonly List m_Update_List = new List(); - private static INetworkUpdateSystem[] m_Update_Array = new INetworkUpdateSystem[0]; - - private static void RunNetworkUpdate() - { - UpdateStage = NetworkUpdateStage.Update; - int arrayLength = m_Update_Array.Length; - for (int i = 0; i < arrayLength; i++) - { - m_Update_Array[i].NetworkUpdate(UpdateStage); - } - } - - private static readonly List m_PreLateUpdate_List = new List(); - private static INetworkUpdateSystem[] m_PreLateUpdate_Array = new INetworkUpdateSystem[0]; - - private static void RunNetworkPreLateUpdate() - { - UpdateStage = NetworkUpdateStage.PreLateUpdate; - int arrayLength = m_PreLateUpdate_Array.Length; - for (int i = 0; i < arrayLength; i++) - { - m_PreLateUpdate_Array[i].NetworkUpdate(UpdateStage); - } - } - - private static readonly List m_PostLateUpdate_List = new List(); - private static INetworkUpdateSystem[] m_PostLateUpdate_Array = new INetworkUpdateSystem[0]; - - private static void RunNetworkPostLateUpdate() - { - UpdateStage = NetworkUpdateStage.PostLateUpdate; - int arrayLength = m_PostLateUpdate_Array.Length; - for (int i = 0; i < arrayLength; i++) - { - m_PostLateUpdate_Array[i].NetworkUpdate(UpdateStage); - } - } } } \ No newline at end of file From 74e6a123920b466c8b5771482fb2c652ea12f5c8 Mon Sep 17 00:00:00 2001 From: "M. Fatih MAR" Date: Thu, 18 Feb 2021 17:40:56 +0000 Subject: [PATCH 13/14] dictionary lookups instead of index access to arrays --- .../Runtime/Core/NetworkUpdateLoop.cs | 57 ++++++++----------- 1 file changed, 24 insertions(+), 33 deletions(-) diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs index 396e654e34..b89b6bc0ba 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs @@ -155,6 +155,21 @@ private static void Initialize() PlayerLoop.SetPlayerLoop(customPlayerLoop); } + static NetworkUpdateLoop() + { + m_UpdateSystem_Sets = new Dictionary>(); + m_UpdateSystem_Arrays = new Dictionary(); + + foreach (NetworkUpdateStage updateStage in Enum.GetValues(typeof(NetworkUpdateStage))) + { + m_UpdateSystem_Sets.Add(updateStage, new HashSet()); + m_UpdateSystem_Arrays.Add(updateStage, new INetworkUpdateSystem[0]); + } + } + + private static readonly Dictionary> m_UpdateSystem_Sets; + private static readonly Dictionary m_UpdateSystem_Arrays; + /// /// The current network update stage being executed. /// @@ -176,11 +191,10 @@ public static void RegisterAllNetworkUpdates(this INetworkUpdateSystem updateSys /// public static void RegisterNetworkUpdate(this INetworkUpdateSystem updateSystem, NetworkUpdateStage updateStage = NetworkUpdateStage.Update) { - int updateStageIndex = (int)updateStage; - if (!m_UpdateSystem_Sets[updateStageIndex].Contains(updateSystem)) + if (!m_UpdateSystem_Sets[updateStage].Contains(updateSystem)) { - m_UpdateSystem_Sets[updateStageIndex].Add(updateSystem); - m_UpdateSystem_Arrays[updateStageIndex] = m_UpdateSystem_Sets[updateStageIndex].ToArray(); + m_UpdateSystem_Sets[updateStage].Add(updateSystem); + m_UpdateSystem_Arrays[updateStage] = m_UpdateSystem_Sets[updateStage].ToArray(); } } @@ -200,44 +214,21 @@ public static void UnregisterAllNetworkUpdates(this INetworkUpdateSystem updateS /// public static void UnregisterNetworkUpdate(this INetworkUpdateSystem updateSystem, NetworkUpdateStage updateStage = NetworkUpdateStage.Update) { - int updateStageIndex = (int)updateStage; - if (m_UpdateSystem_Sets[updateStageIndex].Contains(updateSystem)) + if (m_UpdateSystem_Sets[updateStage].Contains(updateSystem)) { - m_UpdateSystem_Sets[updateStageIndex].Remove(updateSystem); - m_UpdateSystem_Arrays[updateStageIndex] = m_UpdateSystem_Sets[updateStageIndex].ToArray(); + m_UpdateSystem_Sets[updateStage].Remove(updateSystem); + m_UpdateSystem_Arrays[updateStage] = m_UpdateSystem_Sets[updateStage].ToArray(); } } - private static readonly HashSet[] m_UpdateSystem_Sets = - { - new HashSet(), // 0: Update - new HashSet(), // 1: Initialization - new HashSet(), // 2: EarlyUpdate - new HashSet(), // 3: FixedUpdate - new HashSet(), // 4: PreUpdate - new HashSet(), // 5: PreLateUpdate - new HashSet(), // 6: PostLateUpdate - }; - - private static readonly INetworkUpdateSystem[][] m_UpdateSystem_Arrays = - { - new INetworkUpdateSystem[0], // 0: Update - new INetworkUpdateSystem[0], // 1: Initialization - new INetworkUpdateSystem[0], // 2: EarlyUpdate - new INetworkUpdateSystem[0], // 3: FixedUpdate - new INetworkUpdateSystem[0], // 4: PreUpdate - new INetworkUpdateSystem[0], // 5: PreLateUpdate - new INetworkUpdateSystem[0], // 6: PostLateUpdate - }; - private static void RunNetworkUpdateStage(NetworkUpdateStage updateStage) { UpdateStage = updateStage; - int updateStageIndex = (int)updateStage; - int arrayLength = m_UpdateSystem_Arrays[updateStageIndex].Length; + var updateSystems = m_UpdateSystem_Arrays[updateStage]; + int arrayLength = updateSystems.Length; for (int i = 0; i < arrayLength; i++) { - m_UpdateSystem_Arrays[updateStageIndex][i].NetworkUpdate(updateStage); + updateSystems[i].NetworkUpdate(updateStage); } } From 92d9732df283422197cc7eaa95668185482b22d6 Mon Sep 17 00:00:00 2001 From: "M. Fatih MAR" Date: Sat, 20 Feb 2021 11:40:41 +0000 Subject: [PATCH 14/14] optimize array allocation --- .../Runtime/Core/NetworkUpdateLoop.cs | 323 ++++++++++-------- 1 file changed, 184 insertions(+), 139 deletions(-) diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs index b89b6bc0ba..f6d07bbc21 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkUpdateLoop.cs @@ -34,126 +34,9 @@ public enum NetworkUpdateStage : byte /// public static class NetworkUpdateLoop { - [RuntimeInitializeOnLoadMethod] - private static void Initialize() - { - var customPlayerLoop = PlayerLoop.GetCurrentPlayerLoop(); - - for (int i = 0; i < customPlayerLoop.subSystemList.Length; i++) - { - var playerLoopSystem = customPlayerLoop.subSystemList[i]; - - if (playerLoopSystem.type == typeof(Initialization)) - { - var subsystems = playerLoopSystem.subSystemList.ToList(); - { - // insert at the bottom of `Initialization` - subsystems.Add(NetworkInitialization.CreateLoopSystem()); - } - playerLoopSystem.subSystemList = subsystems.ToArray(); - } - else if (playerLoopSystem.type == typeof(EarlyUpdate)) - { - var subsystems = playerLoopSystem.subSystemList.ToList(); - { - int indexOfScriptRunDelayedStartupFrame = subsystems.FindIndex(s => s.type == typeof(EarlyUpdate.ScriptRunDelayedStartupFrame)); - if (indexOfScriptRunDelayedStartupFrame < 0) - { - Debug.LogError($"{nameof(NetworkUpdateLoop)}.{nameof(Initialize)}: Cannot find index of `{nameof(EarlyUpdate.ScriptRunDelayedStartupFrame)}` loop system in `{nameof(EarlyUpdate)}`'s subsystem list!"); - return; - } - - // insert before `EarlyUpdate.ScriptRunDelayedStartupFrame` - subsystems.Insert(indexOfScriptRunDelayedStartupFrame, NetworkEarlyUpdate.CreateLoopSystem()); - } - playerLoopSystem.subSystemList = subsystems.ToArray(); - } - else if (playerLoopSystem.type == typeof(FixedUpdate)) - { - var subsystems = playerLoopSystem.subSystemList.ToList(); - { - int indexOfScriptRunBehaviourFixedUpdate = subsystems.FindIndex(s => s.type == typeof(FixedUpdate.ScriptRunBehaviourFixedUpdate)); - if (indexOfScriptRunBehaviourFixedUpdate < 0) - { - Debug.LogError($"{nameof(NetworkUpdateLoop)}.{nameof(Initialize)}: Cannot find index of `{nameof(FixedUpdate.ScriptRunBehaviourFixedUpdate)}` loop system in `{nameof(FixedUpdate)}`'s subsystem list!"); - return; - } - - // insert before `FixedUpdate.ScriptRunBehaviourFixedUpdate` - subsystems.Insert(indexOfScriptRunBehaviourFixedUpdate, NetworkFixedUpdate.CreateLoopSystem()); - } - playerLoopSystem.subSystemList = subsystems.ToArray(); - } - else if (playerLoopSystem.type == typeof(PreUpdate)) - { - var subsystems = playerLoopSystem.subSystemList.ToList(); - { - int indexOfPhysicsUpdate = subsystems.FindIndex(s => s.type == typeof(PreUpdate.PhysicsUpdate)); - if (indexOfPhysicsUpdate < 0) - { - Debug.LogError($"{nameof(NetworkUpdateLoop)}.{nameof(Initialize)}: Cannot find index of `{nameof(PreUpdate.PhysicsUpdate)}` loop system in `{nameof(PreUpdate)}`'s subsystem list!"); - return; - } - - // insert before `PreUpdate.PhysicsUpdate` - subsystems.Insert(indexOfPhysicsUpdate, NetworkPreUpdate.CreateLoopSystem()); - } - playerLoopSystem.subSystemList = subsystems.ToArray(); - } - else if (playerLoopSystem.type == typeof(Update)) - { - var subsystems = playerLoopSystem.subSystemList.ToList(); - { - int indexOfScriptRunBehaviourUpdate = subsystems.FindIndex(s => s.type == typeof(Update.ScriptRunBehaviourUpdate)); - if (indexOfScriptRunBehaviourUpdate < 0) - { - Debug.LogError($"{nameof(NetworkUpdateLoop)}.{nameof(Initialize)}: Cannot find index of `{nameof(Update.ScriptRunBehaviourUpdate)}` loop system in `{nameof(Update)}`'s subsystem list!"); - return; - } - - // insert before `Update.ScriptRunBehaviourUpdate` - subsystems.Insert(indexOfScriptRunBehaviourUpdate, NetworkUpdate.CreateLoopSystem()); - } - playerLoopSystem.subSystemList = subsystems.ToArray(); - } - else if (playerLoopSystem.type == typeof(PreLateUpdate)) - { - var subsystems = playerLoopSystem.subSystemList.ToList(); - { - int indexOfScriptRunBehaviourLateUpdate = subsystems.FindIndex(s => s.type == typeof(PreLateUpdate.ScriptRunBehaviourLateUpdate)); - if (indexOfScriptRunBehaviourLateUpdate < 0) - { - Debug.LogError($"{nameof(NetworkUpdateLoop)}.{nameof(Initialize)}: Cannot find index of `{nameof(PreLateUpdate.ScriptRunBehaviourLateUpdate)}` loop system in `{nameof(PreLateUpdate)}`'s subsystem list!"); - return; - } - - // insert before `PreLateUpdate.ScriptRunBehaviourLateUpdate` - subsystems.Insert(indexOfScriptRunBehaviourLateUpdate, NetworkPreLateUpdate.CreateLoopSystem()); - } - playerLoopSystem.subSystemList = subsystems.ToArray(); - } - else if (playerLoopSystem.type == typeof(PostLateUpdate)) - { - var subsystems = playerLoopSystem.subSystemList.ToList(); - { - int indexOfPlayerSendFrameComplete = subsystems.FindIndex(s => s.type == typeof(PostLateUpdate.PlayerSendFrameComplete)); - if (indexOfPlayerSendFrameComplete < 0) - { - Debug.LogError($"{nameof(NetworkUpdateLoop)}.{nameof(Initialize)}: Cannot find index of `{nameof(PostLateUpdate.PlayerSendFrameComplete)}` loop system in `{nameof(PostLateUpdate)}`'s subsystem list!"); - return; - } - - // insert after `PostLateUpdate.PlayerSendFrameComplete` - subsystems.Insert(indexOfPlayerSendFrameComplete + 1, NetworkPostLateUpdate.CreateLoopSystem()); - } - playerLoopSystem.subSystemList = subsystems.ToArray(); - } - - customPlayerLoop.subSystemList[i] = playerLoopSystem; - } - - PlayerLoop.SetPlayerLoop(customPlayerLoop); - } + private static readonly Dictionary> m_UpdateSystem_Sets; + private static readonly Dictionary m_UpdateSystem_Arrays; + private const int k_UpdateSystem_InitialArrayCapacity = 1024; static NetworkUpdateLoop() { @@ -163,18 +46,10 @@ static NetworkUpdateLoop() foreach (NetworkUpdateStage updateStage in Enum.GetValues(typeof(NetworkUpdateStage))) { m_UpdateSystem_Sets.Add(updateStage, new HashSet()); - m_UpdateSystem_Arrays.Add(updateStage, new INetworkUpdateSystem[0]); + m_UpdateSystem_Arrays.Add(updateStage, new INetworkUpdateSystem[k_UpdateSystem_InitialArrayCapacity]); } } - private static readonly Dictionary> m_UpdateSystem_Sets; - private static readonly Dictionary m_UpdateSystem_Arrays; - - /// - /// The current network update stage being executed. - /// - public static NetworkUpdateStage UpdateStage; - /// /// Registers a network update system to be executed in all network update stages. /// @@ -191,10 +66,28 @@ public static void RegisterAllNetworkUpdates(this INetworkUpdateSystem updateSys /// public static void RegisterNetworkUpdate(this INetworkUpdateSystem updateSystem, NetworkUpdateStage updateStage = NetworkUpdateStage.Update) { - if (!m_UpdateSystem_Sets[updateStage].Contains(updateSystem)) + var sysSet = m_UpdateSystem_Sets[updateStage]; + if (!sysSet.Contains(updateSystem)) { - m_UpdateSystem_Sets[updateStage].Add(updateSystem); - m_UpdateSystem_Arrays[updateStage] = m_UpdateSystem_Sets[updateStage].ToArray(); + sysSet.Add(updateSystem); + + int setLen = sysSet.Count; + var sysArr = m_UpdateSystem_Arrays[updateStage]; + int arrLen = sysArr.Length; + + if (setLen > arrLen) + { + // double capacity + sysArr = m_UpdateSystem_Arrays[updateStage] = new INetworkUpdateSystem[arrLen *= 2]; + } + + sysSet.CopyTo(sysArr); + + if (setLen < arrLen) + { + // null terminator + sysArr[setLen] = null; + } } } @@ -214,21 +107,46 @@ public static void UnregisterAllNetworkUpdates(this INetworkUpdateSystem updateS /// public static void UnregisterNetworkUpdate(this INetworkUpdateSystem updateSystem, NetworkUpdateStage updateStage = NetworkUpdateStage.Update) { - if (m_UpdateSystem_Sets[updateStage].Contains(updateSystem)) + var sysSet = m_UpdateSystem_Sets[updateStage]; + if (sysSet.Contains(updateSystem)) { - m_UpdateSystem_Sets[updateStage].Remove(updateSystem); - m_UpdateSystem_Arrays[updateStage] = m_UpdateSystem_Sets[updateStage].ToArray(); + sysSet.Remove(updateSystem); + + int setLen = sysSet.Count; + var sysArr = m_UpdateSystem_Arrays[updateStage]; + int arrLen = sysArr.Length; + + sysSet.CopyTo(sysArr); + + if (setLen < arrLen) + { + // null terminator + sysArr[setLen] = null; + } } } + /// + /// The current network update stage being executed. + /// + public static NetworkUpdateStage UpdateStage; + private static void RunNetworkUpdateStage(NetworkUpdateStage updateStage) { UpdateStage = updateStage; - var updateSystems = m_UpdateSystem_Arrays[updateStage]; - int arrayLength = updateSystems.Length; - for (int i = 0; i < arrayLength; i++) + + var sysArr = m_UpdateSystem_Arrays[updateStage]; + int arrLen = sysArr.Length; + for (int curIdx = 0; curIdx < arrLen; curIdx++) { - updateSystems[i].NetworkUpdate(updateStage); + var curSys = sysArr[curIdx]; + if (curSys == null) + { + // null terminator + break; + } + + curSys.NetworkUpdate(updateStage); } } @@ -315,5 +233,132 @@ public static PlayerLoopSystem CreateLoopSystem() }; } } + + [RuntimeInitializeOnLoadMethod] + private static void Initialize() + { + var customPlayerLoop = PlayerLoop.GetCurrentPlayerLoop(); + + for (int i = 0; i < customPlayerLoop.subSystemList.Length; i++) + { + var playerLoopSystem = customPlayerLoop.subSystemList[i]; + + if (playerLoopSystem.type == typeof(Initialization)) + { + var subsystems = playerLoopSystem.subSystemList.ToList(); + { + // insert at the bottom of `Initialization` + subsystems.Add(NetworkInitialization.CreateLoopSystem()); + } + playerLoopSystem.subSystemList = subsystems.ToArray(); + } + else if (playerLoopSystem.type == typeof(EarlyUpdate)) + { + var subsystems = playerLoopSystem.subSystemList.ToList(); + { + int subsystemCount = subsystems.Count; + for (int k = 0; k < subsystemCount; k++) + { + if (subsystems[k].type == typeof(EarlyUpdate.ScriptRunDelayedStartupFrame)) + { + // insert before `EarlyUpdate.ScriptRunDelayedStartupFrame` + subsystems.Insert(k, NetworkEarlyUpdate.CreateLoopSystem()); + break; + } + } + } + playerLoopSystem.subSystemList = subsystems.ToArray(); + } + else if (playerLoopSystem.type == typeof(FixedUpdate)) + { + var subsystems = playerLoopSystem.subSystemList.ToList(); + { + int subsystemCount = subsystems.Count; + for (int k = 0; k < subsystemCount; k++) + { + if (subsystems[k].type == typeof(FixedUpdate.ScriptRunBehaviourFixedUpdate)) + { + // insert before `FixedUpdate.ScriptRunBehaviourFixedUpdate` + subsystems.Insert(k, NetworkFixedUpdate.CreateLoopSystem()); + break; + } + } + } + playerLoopSystem.subSystemList = subsystems.ToArray(); + } + else if (playerLoopSystem.type == typeof(PreUpdate)) + { + var subsystems = playerLoopSystem.subSystemList.ToList(); + { + int subsystemCount = subsystems.Count; + for (int k = 0; k < subsystemCount; k++) + { + if (subsystems[k].type == typeof(PreUpdate.PhysicsUpdate)) + { + // insert before `PreUpdate.PhysicsUpdate` + subsystems.Insert(k, NetworkPreUpdate.CreateLoopSystem()); + break; + } + } + } + playerLoopSystem.subSystemList = subsystems.ToArray(); + } + else if (playerLoopSystem.type == typeof(Update)) + { + var subsystems = playerLoopSystem.subSystemList.ToList(); + { + int subsystemCount = subsystems.Count; + for (int k = 0; k < subsystemCount; k++) + { + if (subsystems[k].type == typeof(Update.ScriptRunBehaviourUpdate)) + { + // insert before `Update.ScriptRunBehaviourUpdate` + subsystems.Insert(k, NetworkUpdate.CreateLoopSystem()); + break; + } + } + } + playerLoopSystem.subSystemList = subsystems.ToArray(); + } + else if (playerLoopSystem.type == typeof(PreLateUpdate)) + { + var subsystems = playerLoopSystem.subSystemList.ToList(); + { + int subsystemCount = subsystems.Count; + for (int k = 0; k < subsystemCount; k++) + { + if (subsystems[k].type == typeof(PreLateUpdate.ScriptRunBehaviourLateUpdate)) + { + // insert before `PreLateUpdate.ScriptRunBehaviourLateUpdate` + subsystems.Insert(k, NetworkPreLateUpdate.CreateLoopSystem()); + break; + } + } + } + playerLoopSystem.subSystemList = subsystems.ToArray(); + } + else if (playerLoopSystem.type == typeof(PostLateUpdate)) + { + var subsystems = playerLoopSystem.subSystemList.ToList(); + { + int subsystemCount = subsystems.Count; + for (int k = 0; k < subsystemCount; k++) + { + if (subsystems[k].type == typeof(PostLateUpdate.PlayerSendFrameComplete)) + { + // insert after `PostLateUpdate.PlayerSendFrameComplete` + subsystems.Insert(k + 1, NetworkPostLateUpdate.CreateLoopSystem()); + break; + } + } + } + playerLoopSystem.subSystemList = subsystems.ToArray(); + } + + customPlayerLoop.subSystemList[i] = playerLoopSystem; + } + + PlayerLoop.SetPlayerLoop(customPlayerLoop); + } } } \ No newline at end of file