示例#1
0
        // 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)
        {
            if (components.Length > 64)
            {
                if (LogFilter.logError)
                {
                    Debug.LogError("Only 64 NetworkBehaviour components are allowed for NetworkIdentity: " + name + " because of the dirtyComponentMask");
                }
                return(false);
            }

            // 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)
            {
                // 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.logDebug)
                    {
                        Debug.Log("OnSerializeAllSafely: " + name + " -> " + comp.GetType() + " initial=" + initialState);
                    }
                    OnSerializeSafely(comp, payload, initialState);

                    // Clear dirty bits only if we are synchronizing data and not sending a spawn message.
                    // This preserves the behavior in HLAPI
                    if (!initialState)
                    {
                        comp.ClearAllDirtyBits();
                    }
                }
            }

            // 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);
        }
示例#2
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        internal void OnDeserializeSafely(NetworkBehaviour comp, NetworkReader reader, bool initialState)
        {
            // extract data length and data safely, untouched by user code
            // -> returns empty array if length is 0, so .Length is always the proper length
            byte[] bytes = reader.ReadBytesAndSize();
            if (LogFilter.logDebug)
            {
                Debug.Log("OnDeserializeSafely extracted: " + comp.name + " component=" + comp.GetType() + " sceneId=" + m_SceneId + " length=" + bytes.Length);
            }

            // call OnDeserialize with a temporary reader, so that the
            // original one can't be messed with. we also wrap it in a
            // try-catch block so there's no way to mess up another
            // component's deserialization
            try
            {
                comp.OnDeserialize(new NetworkReader(bytes), initialState);
            }
            catch (Exception e)
            {
                // show a detailed error and let the user know what went wrong
                Debug.LogError("OnDeserialize failed for: object=" + name + " component=" + comp.GetType() + " sceneId=" + m_SceneId + " length=" + bytes.Length + ". Possible Reasons:\n  * Do " + comp.GetType() + "'s OnSerialize and OnDeserialize calls write the same amount of data(" + bytes.Length + " bytes)? \n  * Was there an exception in " + comp.GetType() + "'s OnSerialize/OnDeserialize code?\n  * Are the server and client the exact same project?\n  * Maybe this OnDeserialize call was meant for another GameObject? The sceneIds can easily get out of sync if the Hierarchy was modified only in the client OR the server. Try rebuilding both.\n\n" + e.ToString());
            }
        }
示例#3
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        internal void OnDeserializeSafely(NetworkBehaviour comp, NetworkReader reader, bool initialState)
        {
            // read header as 4 bytes
            int contentSize = reader.ReadInt32();

            // read content
            byte[] bytes = reader.ReadBytes(contentSize);
            if (LogFilter.Debug)
            {
                Debug.Log("OnDeserializeSafely extracted: " + comp.name + " component=" + comp.GetType() + " sceneId=" + m_SceneId + " length=" + bytes.Length);
            }

            // call OnDeserialize with a temporary reader, so that the
            // original one can't be messed with. we also wrap it in a
            // try-catch block so there's no way to mess up another
            // component's deserialization
            try
            {
                NetworkReader componentReader = new NetworkReader(bytes);
                comp.OnDeserialize(componentReader, initialState);
                if (componentReader.Position != componentReader.Length)
                {
                    Debug.LogWarning("OnDeserialize didn't read the full " + bytes.Length + " bytes for object:" + name + " component=" + comp.GetType() + " sceneId=" + m_SceneId + ". Make sure that OnSerialize and OnDeserialize write/read the same amount of data in all cases.");
                }
            }
            catch (Exception e)
            {
                // show a detailed error and let the user know what went wrong
                Debug.LogError("OnDeserialize failed for: object=" + name + " component=" + comp.GetType() + " sceneId=" + m_SceneId + " length=" + bytes.Length + ". Possible Reasons:\n  * Do " + comp.GetType() + "'s OnSerialize and OnDeserialize calls write the same amount of data(" + bytes.Length + " bytes)? \n  * Was there an exception in " + comp.GetType() + "'s OnSerialize/OnDeserialize code?\n  * Are the server and client the exact same project?\n  * Maybe this OnDeserialize call was meant for another GameObject? The sceneIds can easily get out of sync if the Hierarchy was modified only in the client OR the server. Try rebuilding both.\n\n" + e.ToString());
            }
        }
示例#4
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        // vis2k: readstring bug prevention: https://issuetracker.unity3d.com/issues/unet-networkwriter-dot-write-causing-readstring-slash-readbytes-out-of-range-errors-in-clients
        // -> OnSerialize writes length,componentData,length,componentData,...
        // -> OnDeserialize carefully extracts each data, then deserializes each component with separate readers
        //    -> it will be impossible to read too many or too few bytes in OnDeserialize
        //    -> we can properly track down errors
        internal bool OnSerializeSafely(NetworkBehaviour comp, NetworkWriter writer, bool initialState)
        {
            // serialize into a temporary writer
            NetworkWriter temp   = new NetworkWriter();
            bool          result = false;

            try
            {
                result = comp.OnSerialize(temp, initialState);
            }
            catch (Exception e)
            {
                // show a detailed error and let the user know what went wrong
                Debug.LogError("OnSerialize failed for: object=" + name + " component=" + comp.GetType() + " sceneId=" + m_SceneId + "\n\n" + e.ToString());
            }
            byte[] bytes = temp.ToArray();
            if (LogFilter.logDebug)
            {
                Debug.Log("OnSerializeSafely written for object=" + comp.name + " component=" + comp.GetType() + " sceneId=" + m_SceneId + " length=" + bytes.Length);
            }

            // original HLAPI had a warning in UNetUpdate() in case of large state updates. let's move it here, might
            // be useful for debugging.
            if (bytes.Length > Transport.MaxPacketSize)
            {
                if (LogFilter.logWarn)
                {
                    Debug.LogWarning("Large state update of " + bytes.Length + " bytes for netId:" + netId + " from script:" + comp);
                }
            }

            // serialize length,data into the real writer, untouched by user code
            writer.WriteBytesAndSize(bytes);
            return(result);
        }
示例#5
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        // vis2k: readstring bug prevention: https://issuetracker.unity3d.com/issues/unet-networkwriter-dot-write-causing-readstring-slash-readbytes-out-of-range-errors-in-clients
        // -> OnSerialize writes length,componentData,length,componentData,...
        // -> OnDeserialize carefully extracts each data, then deserializes each component with separate readers
        //    -> it will be impossible to read too many or too few bytes in OnDeserialize
        //    -> we can properly track down errors
        internal bool OnSerializeSafely(NetworkBehaviour comp, NetworkWriter writer, bool initialState)
        {
            // write placeholder length bytes
            // (jumping back later is WAY faster than allocating a temporary
            //  writer for the payload, then writing payload.size, payload)
            int headerPosition = writer.Position;

            writer.Write((int)0);
            int contentPosition = writer.Position;

            // write payload
            bool result = false;

            try
            {
                result = comp.OnSerialize(writer, initialState);
            }
            catch (Exception e)
            {
                // show a detailed error and let the user know what went wrong
                Debug.LogError("OnSerialize failed for: object=" + name + " component=" + comp.GetType() + " sceneId=" + m_SceneId + "\n\n" + e.ToString());
            }
            int endPosition = writer.Position;

            // fill in length now
            writer.Position = headerPosition;
            writer.Write(endPosition - contentPosition);
            writer.Position = endPosition;

            if (LogFilter.Debug)
            {
                Debug.Log("OnSerializeSafely written for object=" + comp.name + " component=" + comp.GetType() + " sceneId=" + m_SceneId + "header@" + headerPosition + " content@" + contentPosition + " end@" + endPosition + " contentSize=" + (endPosition - contentPosition));
            }

            return(result);
        }