Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
c729148
NetworkPrefab registration and default PlayerPrefab
NoelStephensUnity Apr 16, 2021
677b49e
Merge branch 'develop' into feat/mtt640
NoelStephensUnity Apr 16, 2021
d873ecc
refactor: Naming, Migration, and PlayerPrefab
NoelStephensUnity Apr 16, 2021
59511f1
refactor: PlayerPrefab assignment
NoelStephensUnity Apr 16, 2021
a217e7a
refactor: player prefab selection and blank new entries
NoelStephensUnity Apr 17, 2021
2559481
style: comments
NoelStephensUnity Apr 17, 2021
84f0942
style: property names and comments
NoelStephensUnity Apr 17, 2021
b78403e
refactor: Client Sync and Comments
NoelStephensUnity Apr 17, 2021
c600724
style: minor change
NoelStephensUnity Apr 17, 2021
97a41bc
Merge branch 'develop' into feat/mtt640
NoelStephensUnity Apr 20, 2021
9558732
Merge branch 'develop' into feat/mtt640
NoelStephensUnity Apr 20, 2021
e799b47
refactor: remove CreatePlayerPrefab
NoelStephensUnity Apr 20, 2021
5926c3c
refactor: cleaning up using
NoelStephensUnity Apr 20, 2021
481e862
style: PlayerPrefab tooltip
NoelStephensUnity Apr 20, 2021
7f2781c
style: spaces between slashes and comment text body
NoelStephensUnity Apr 20, 2021
3de2cac
fix: clearing network prefab links
NoelStephensUnity Apr 20, 2021
bb91f17
refactor: NetworkConfig compatibility, NetworkPrefab, and Style
NoelStephensUnity Apr 21, 2021
41551a0
refactor: Object Synchronization
NoelStephensUnity Apr 21, 2021
c26c148
Merge branch 'develop' into refactor/mtt640-sceneobjects
NoelStephensUnity Apr 26, 2021
d4e702e
refactor merge
NoelStephensUnity Apr 26, 2021
8b5ea09
Merge branch 'develop' into refactor/mtt640-sceneobjects
NoelStephensUnity Apr 27, 2021
d6404e9
Merge branch 'develop' into refactor/mtt640-sceneobjects
NoelStephensUnity Apr 27, 2021
02d05db
minor update
0xFA11 Apr 27, 2021
1ba6d6b
minor update
0xFA11 Apr 27, 2021
41478ff
minor update
0xFA11 Apr 27, 2021
43f39b3
minor update
0xFA11 Apr 27, 2021
034d8b3
Merge branch 'develop' into refactor/mtt640-sceneobjects
NoelStephensUnity Apr 27, 2021
51835db
style: Comments and Standards
NoelStephensUnity Apr 27, 2021
6d2d094
Update com.unity.multiplayer.mlapi/Runtime/Core/NetworkObject.cs
NoelStephensUnity Apr 27, 2021
e67a4c2
Merge branch 'develop' into refactor/mtt640-sceneobjects
NoelStephensUnity Apr 27, 2021
34c07f3
Merge branch 'refactor/mtt640-sceneobjects' of https://github.com/Uni…
NoelStephensUnity Apr 27, 2021
36b692f
refactor: Naming updates, comments, an d logic
NoelStephensUnity Apr 27, 2021
d232557
test: NetworkObject scene serialization test
NoelStephensUnity Apr 28, 2021
be9e635
refactor test
NoelStephensUnity Apr 28, 2021
750b2bb
style
NoelStephensUnity Apr 28, 2021
e9137ae
style: invalidNetworkObjectFrequency
NoelStephensUnity Apr 28, 2021
cd956cb
style: spelling
NoelStephensUnity Apr 28, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 1 addition & 45 deletions com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1600,51 +1600,7 @@ internal void HandleApproval(ulong ownerClientId, bool createPlayerObject, uint?

for (int i = 0; i < m_ObservedObjects.Count; i++)
{
var observedObject = m_ObservedObjects[i];
writer.WriteBool(observedObject.IsPlayerObject);
writer.WriteUInt64Packed(observedObject.NetworkObjectId);
writer.WriteUInt64Packed(observedObject.OwnerClientId);

NetworkObject parent = null;

if (!observedObject.AlwaysReplicateAsRoot && observedObject.transform.parent != null)
{
parent = observedObject.transform.parent.GetComponent<NetworkObject>();
}

if (parent == null)
{
writer.WriteBool(false);
}
else
{
writer.WriteBool(true);
writer.WriteUInt64Packed(parent.NetworkObjectId);
}

writer.WriteBool(observedObject.IsSceneObject ?? true);
writer.WriteUInt32Packed(observedObject.GlobalObjectIdHash);

if (observedObject.IncludeTransformWhenSpawning == null || observedObject.IncludeTransformWhenSpawning(ownerClientId))
{
writer.WriteBool(true);
writer.WriteSinglePacked(observedObject.transform.position.x);
writer.WriteSinglePacked(observedObject.transform.position.y);
writer.WriteSinglePacked(observedObject.transform.position.z);

writer.WriteSinglePacked(observedObject.transform.rotation.eulerAngles.x);
writer.WriteSinglePacked(observedObject.transform.rotation.eulerAngles.y);
writer.WriteSinglePacked(observedObject.transform.rotation.eulerAngles.z);
}
else
{
writer.WriteBool(false);
}

if (NetworkConfig.EnableNetworkVariable)
{
observedObject.WriteNetworkVariableData(buffer, ownerClientId);
}
m_ObservedObjects[i].SerializeSceneObject(writer, ownerClientId);
Comment thread
NoelStephensUnity marked this conversation as resolved.
}

MessageSender.Send(ownerClientId, NetworkConstants.CONNECTION_APPROVED, NetworkChannel.Internal, buffer);
Expand Down
181 changes: 181 additions & 0 deletions com.unity.multiplayer.mlapi/Runtime/Core/NetworkObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using MLAPI.Logging;
using MLAPI.Serialization.Pooled;
using MLAPI.Transports;
using MLAPI.Serialization;
using UnityEngine;

namespace MLAPI
Expand Down Expand Up @@ -598,5 +599,185 @@ internal NetworkBehaviour GetNetworkBehaviourAtOrderIndex(ushort index)

return ChildNetworkBehaviours[index];
}

/// <summary>
/// Used to serialize a NetworkObjects during scene syncrhonization 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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the wonderful comments

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 de-serialization 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;
}
}
}

/// <summary>
/// Ueed to deserialize a serialized scene object which occurs
/// when the client is approved or during a scene transition
/// </summary>
/// <param name="objectStream">inbound stream</param>
/// <param name="reader">reader for the stream</param>
/// <param name="networkManager">NetworkManager instance</param>
/// <returns>optional to use NetworkObject deserialized</returns>
internal static NetworkObject DeserializeSceneObject(NetworkBuffer objectStream, NetworkReader reader, NetworkManager networkManager)
{
var isPlayerObject = reader.ReadBool();
var networkId = reader.ReadUInt64Packed();
var ownerClientId = reader.ReadUInt64Packed();
var hasParent = reader.ReadBool();
ulong? parentNetworkId = null;

if (hasParent)
{
parentNetworkId = reader.ReadUInt32Packed();
}

var isSceneObject = reader.ReadBool();

var prefabHash = reader.ReadUInt32Packed();
Vector3? position = null;
Quaternion? rotation = null;

// Check to see if we have position and rotation values that follows
if (reader.ReadBool())
{
position = new Vector3(reader.ReadSinglePacked(), reader.ReadSinglePacked(), reader.ReadSinglePacked());
rotation = Quaternion.Euler(reader.ReadSinglePacked(), reader.ReadSinglePacked(), reader.ReadSinglePacked());
}

//Attemp to create a local NetworkObject
var networkObject = networkManager.SpawnManager.CreateLocalNetworkObject(isSceneObject, prefabHash, ownerClientId, parentNetworkId, position, rotation);

// Determine if this NetworkObject has NetworkVariable data to read
var networkVariableDataIsIncluded = reader.ReadBool();

if (networkVariableDataIsIncluded)
{
// (See Part 1 above in the NetworkObject.SerializeSceneObject method to better understand this)
// Part 2: This makes sure that if one NetworkObject fails to construct (for whatever reason) then we can "skip past"
// that specific NetworkObject but continue processing any remaining serialized NetworkObjects as opposed to just
// throwing an exception and skipping the remaining (if any) NetworkObjects. This will prevent one misconfigured
// issue (or more) from breaking the entire loading process.
var networkVariableDataSize = reader.ReadUInt32();
if (networkObject == null)
{
// Log the error that the NetworkObject failed to construct
Debug.LogError($"Failed to spawn {nameof(NetworkObject)} for Hash {prefabHash}.");

// If we failed to load this NetworkObject, then skip past the network variable data
objectStream.Position += networkVariableDataSize;

// We have nothing left to do here.
return null;
}
}

// Spawn the NetworkObject
networkManager.SpawnManager.SpawnNetworkObjectLocally(networkObject, networkId, isSceneObject, isPlayerObject, ownerClientId, objectStream, false, 0, true, false);

var bufferQueue = networkManager.BufferManager.ConsumeBuffersForNetworkId(networkId);

// Apply buffered messages
if (bufferQueue != null)
{
while (bufferQueue.Count > 0)
{
Messaging.Buffering.BufferManager.BufferedMessage message = bufferQueue.Dequeue();
networkManager.HandleIncomingData(message.SenderClientId, message.NetworkChannel, new ArraySegment<byte>(message.NetworkBuffer.GetBuffer(), (int)message.NetworkBuffer.Position, (int)message.NetworkBuffer.Length), message.ReceiveTime, false);
Messaging.Buffering.BufferManager.RecycleConsumedBufferedMessage(message);
}
}

return networkObject;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -131,43 +131,7 @@ void DelayedSpawnAction(Stream continuationStream)
var objectCount = continuationReader.ReadUInt32Packed();
for (int i = 0; i < objectCount; i++)
{
var isPlayerObject = continuationReader.ReadBool();
var networkId = continuationReader.ReadUInt64Packed();
var ownerId = continuationReader.ReadUInt64Packed();
var hasParent = continuationReader.ReadBool();
ulong? parentNetworkId = null;

if (hasParent)
{
parentNetworkId = continuationReader.ReadUInt64Packed();
}

var softSync = continuationReader.ReadBool();
var prefabHash = continuationReader.ReadUInt32Packed();

Vector3? pos = null;
Quaternion? rot = null;
if (continuationReader.ReadBool())
{
pos = new Vector3(continuationReader.ReadSinglePacked(), continuationReader.ReadSinglePacked(), continuationReader.ReadSinglePacked());
rot = Quaternion.Euler(continuationReader.ReadSinglePacked(), continuationReader.ReadSinglePacked(), continuationReader.ReadSinglePacked());
}

var networkObject = NetworkManager.SpawnManager.CreateLocalNetworkObject(softSync, prefabHash, ownerId, parentNetworkId, pos, rot);
NetworkManager.SpawnManager.SpawnNetworkObjectLocally(networkObject, networkId, softSync, isPlayerObject, ownerId, continuationStream, false, 0, true, false);

Queue<BufferManager.BufferedMessage> bufferQueue = NetworkManager.BufferManager.ConsumeBuffersForNetworkId(networkId);

// Apply buffered messages
if (bufferQueue != null)
{
while (bufferQueue.Count > 0)
{
BufferManager.BufferedMessage message = bufferQueue.Dequeue();
NetworkManager.HandleIncomingData(message.SenderClientId, message.NetworkChannel, new ArraySegment<byte>(message.NetworkBuffer.GetBuffer(), (int)message.NetworkBuffer.Position, (int)message.NetworkBuffer.Length), message.ReceiveTime, false);
BufferManager.RecycleConsumedBufferedMessage(message);
}
}
NetworkObject.DeserializeSceneObject(continuationStream as NetworkBuffer, continuationReader, m_NetworkManager);
}

NetworkManager.SpawnManager.CleanDiffedSceneObjects();
Expand Down
Loading