diff --git a/Mirror/Runtime/NetworkIdentity.cs b/Mirror/Runtime/NetworkIdentity.cs index 0da903e9d..0ba433126 100644 --- a/Mirror/Runtime/NetworkIdentity.cs +++ b/Mirror/Runtime/NetworkIdentity.cs @@ -436,32 +436,32 @@ internal bool OnSerializeSafely(NetworkBehaviour comp, NetworkWriter writer, boo } // serialize all components (or only dirty ones if not initial state) - // -> returns TRUE if any date other than dirtyMask was written! - internal bool OnSerializeAllSafely(NetworkBehaviour[] components, NetworkWriter writer, bool initialState) + // -> returns serialized data of everything dirty, null if nothing was dirty + internal byte[] OnSerializeAllSafely(bool initialState) { - if (components.Length > 64) + if (m_NetworkBehaviours.Length > 64) { Debug.LogError("Only 64 NetworkBehaviour components are allowed for NetworkIdentity: " + name + " because of the dirtyComponentMask"); - return false; + return null; } + ulong dirtyComponentsMask = GetDirtyMask(m_NetworkBehaviours, initialState); - // loop through all components only once and then write dirty+payload into the writer afterwards - ulong dirtyComponentsMask = 0L; - NetworkWriter payload = new NetworkWriter(); - for (int i = 0; i < components.Length; ++i) + if (dirtyComponentsMask == 0L) + return null; + + NetworkWriter writer = new NetworkWriter(); + writer.WritePackedUInt64(dirtyComponentsMask); // WritePacked64 so we don't write full 8 bytes if we don't have to + + foreach (NetworkBehaviour comp in m_NetworkBehaviours) { // is this component dirty? // -> always serialize if initialState so all components are included in spawn packet // -> note: IsDirty() is false if the component isn't dirty or sendInterval isn't elapsed yet - NetworkBehaviour comp = m_NetworkBehaviours[i]; if (initialState || comp.IsDirty()) { - // set bit #i to 1 in dirty mask - dirtyComponentsMask |= (ulong)(1L << i); - // serialize the data if (LogFilter.Debug) { Debug.Log("OnSerializeAllSafely: " + name + " -> " + comp.GetType() + " initial=" + initialState); } - OnSerializeSafely(comp, payload, initialState); + OnSerializeSafely(comp, writer, initialState); // Clear dirty bits only if we are synchronizing data and not sending a spawn message. // This preserves the behavior in HLAPI @@ -471,22 +471,25 @@ internal bool OnSerializeAllSafely(NetworkBehaviour[] components, NetworkWriter } } } - - // did we write anything? then write dirty, payload and return true - if (dirtyComponentsMask != 0L) - { - byte[] payloadBytes = payload.ToArray(); - writer.WritePackedUInt64(dirtyComponentsMask); // WritePacked64 so we don't write full 8 bytes if we don't have to - writer.Write(payloadBytes, 0, payloadBytes.Length); - return true; - } - - // didn't write anything, return false - return false; + + return writer.ToArray(); } - // extra version that uses m_NetworkBehaviours so we can call it from the outside - internal void OnSerializeAllSafely(NetworkWriter writer, bool initialState) { OnSerializeAllSafely(m_NetworkBehaviours, writer, initialState); } + private ulong GetDirtyMask(NetworkBehaviour[] components, bool initialState) + { + // loop through all components only once and then write dirty+payload into the writer afterwards + ulong dirtyComponentsMask = 0L; + for (int i = 0; i < components.Length; ++i) + { + NetworkBehaviour comp = components[i]; + if (initialState || comp.IsDirty()) + { + dirtyComponentsMask |= (ulong)(1L << i); + } + } + + return dirtyComponentsMask; + } //////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -654,19 +657,16 @@ internal void HandleRPC(int componentIndex, int cmdHash, NetworkReader reader) // invoked by unity runtime immediately after the regular "Update()" function. internal void UNetUpdate() { - if (m_NetworkBehaviours.Any(comp => comp.IsDirty())) + // serialize all the dirty components and send (if any were dirty) + byte[] payload = OnSerializeAllSafely(false); + if (payload != null) { - // serialize all the dirty components and send (if any were dirty) - NetworkWriter writer = new NetworkWriter(); - if (OnSerializeAllSafely(m_NetworkBehaviours, writer, false)) - { - // construct message and send - UpdateVarsMessage message = new UpdateVarsMessage(); - message.netId = netId; - message.payload = writer.ToArray(); + // construct message and send + UpdateVarsMessage message = new UpdateVarsMessage(); + message.netId = netId; + message.payload = payload; - NetworkServer.SendToReady(gameObject, (short)MsgType.UpdateVars, message); - } + NetworkServer.SendToReady(gameObject, (short)MsgType.UpdateVars, message); } } diff --git a/Mirror/Runtime/NetworkServer.cs b/Mirror/Runtime/NetworkServer.cs index 5f6840b81..1567501fa 100644 --- a/Mirror/Runtime/NetworkServer.cs +++ b/Mirror/Runtime/NetworkServer.cs @@ -951,9 +951,7 @@ internal static void SendSpawnMessage(NetworkIdentity uv, NetworkConnection conn msg.rotation = uv.transform.rotation; // serialize all components with initialState = true - NetworkWriter writer = new NetworkWriter(); - uv.OnSerializeAllSafely(writer, true); - msg.payload = writer.ToArray(); + msg.payload = uv.OnSerializeAllSafely(true); // conn is != null when spawning it for a client if (conn != null) @@ -975,9 +973,7 @@ internal static void SendSpawnMessage(NetworkIdentity uv, NetworkConnection conn msg.position = uv.transform.position; // include synch data - NetworkWriter writer = new NetworkWriter(); - uv.OnSerializeAllSafely(writer, true); - msg.payload = writer.ToArray(); + msg.payload = uv.OnSerializeAllSafely(true); // conn is != null when spawning it for a client if (conn != null)