/// <summary> /// Used to serialize a NetworkObjects during scene synchronization that occurs /// upon a client being approved or a scene transition. /// </summary> /// <param name="writer">writer into the outbound stream</param> /// <param name="targetClientId">clientid we are targeting</param> internal void SerializeSceneObject(NetworkWriter writer, ulong targetClientId) { writer.WriteBool(IsPlayerObject); writer.WriteUInt64Packed(NetworkObjectId); writer.WriteUInt64Packed(OwnerClientId); NetworkObject parentNetworkObject = null; if (!AlwaysReplicateAsRoot && transform.parent != null) { parentNetworkObject = transform.parent.GetComponent <NetworkObject>(); } if (parentNetworkObject == null) { // We don't have a parent writer.WriteBool(false); } else { // We do have a parent writer.WriteBool(true); // Write the parent's NetworkObjectId to be used for linking back to the child writer.WriteUInt64Packed(parentNetworkObject.NetworkObjectId); } // Write if we are a scene object or not writer.WriteBool(IsSceneObject ?? true); // Write the hash for this NetworkObject writer.WriteUInt32Packed(GlobalObjectIdHash); if (IncludeTransformWhenSpawning == null || IncludeTransformWhenSpawning(OwnerClientId)) { // Set the position and rotation data marker to true (i.e. flag to know, when reading from the stream, that position and rotation data follows). writer.WriteBool(true); // Write position writer.WriteSinglePacked(transform.position.x); writer.WriteSinglePacked(transform.position.y); writer.WriteSinglePacked(transform.position.z); // Write rotation writer.WriteSinglePacked(transform.rotation.eulerAngles.x); writer.WriteSinglePacked(transform.rotation.eulerAngles.y); writer.WriteSinglePacked(transform.rotation.eulerAngles.z); } else { // Set the position and rotation data marker to false (i.e. flag to know, when reading from the stream, that position and rotation data *was not included*) writer.WriteBool(false); } // Write whether we are including network variable data writer.WriteBool(NetworkManager.NetworkConfig.EnableNetworkVariable); //If we are including NetworkVariable data if (NetworkManager.NetworkConfig.EnableNetworkVariable) { var buffer = writer.GetStream() as NetworkBuffer; // Write placeholder size, NOT as a packed value, initially as zero (i.e. we do not know how much NetworkVariable data will be written yet) writer.WriteUInt32(0); // Mark our current position before we potentially write any NetworkVariable data var positionBeforeNetworkVariableData = buffer.Position; // Write network variable data WriteNetworkVariableData(buffer, targetClientId); // If our current buffer position is greater than our positionBeforeNetworkVariableData then we wrote NetworkVariable data // Part 1: This will include the total NetworkVariable data size, if there was NetworkVariable data written, to the stream // in order to be able to skip past this entry on the deserialization side in the event this NetworkObject fails to be // constructed (See Part 2 below in the DeserializeSceneObject method) if (buffer.Position > positionBeforeNetworkVariableData) { // Store our current stream buffer position var endOfNetworkVariableData = buffer.Position; // Calculate the total NetworkVariable data size written var networkVariableDataSize = endOfNetworkVariableData - positionBeforeNetworkVariableData; // Move the stream position back to just before we wrote our size (we include the unpacked UInt32 data size placeholder) buffer.Position = positionBeforeNetworkVariableData - sizeof(uint); // Now write the actual data size written into our unpacked UInt32 placeholder position writer.WriteUInt32((uint)(networkVariableDataSize)); // Finally, revert the buffer position back to the end of the network variable data written buffer.Position = endOfNetworkVariableData; } } }