-
Notifications
You must be signed in to change notification settings - Fork 459
refactor: scene object serialization consolidation and improved handling #756
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
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 677b49e
Merge branch 'develop' into feat/mtt640
NoelStephensUnity d873ecc
refactor: Naming, Migration, and PlayerPrefab
NoelStephensUnity 59511f1
refactor: PlayerPrefab assignment
NoelStephensUnity a217e7a
refactor: player prefab selection and blank new entries
NoelStephensUnity 2559481
style: comments
NoelStephensUnity 84f0942
style: property names and comments
NoelStephensUnity b78403e
refactor: Client Sync and Comments
NoelStephensUnity c600724
style: minor change
NoelStephensUnity 97a41bc
Merge branch 'develop' into feat/mtt640
NoelStephensUnity 9558732
Merge branch 'develop' into feat/mtt640
NoelStephensUnity e799b47
refactor: remove CreatePlayerPrefab
NoelStephensUnity 5926c3c
refactor: cleaning up using
NoelStephensUnity 481e862
style: PlayerPrefab tooltip
NoelStephensUnity 7f2781c
style: spaces between slashes and comment text body
NoelStephensUnity 3de2cac
fix: clearing network prefab links
NoelStephensUnity bb91f17
refactor: NetworkConfig compatibility, NetworkPrefab, and Style
NoelStephensUnity 41551a0
refactor: Object Synchronization
NoelStephensUnity c26c148
Merge branch 'develop' into refactor/mtt640-sceneobjects
NoelStephensUnity d4e702e
refactor merge
NoelStephensUnity 8b5ea09
Merge branch 'develop' into refactor/mtt640-sceneobjects
NoelStephensUnity d6404e9
Merge branch 'develop' into refactor/mtt640-sceneobjects
NoelStephensUnity 02d05db
minor update
0xFA11 1ba6d6b
minor update
0xFA11 41478ff
minor update
0xFA11 43f39b3
minor update
0xFA11 034d8b3
Merge branch 'develop' into refactor/mtt640-sceneobjects
NoelStephensUnity 51835db
style: Comments and Standards
NoelStephensUnity 6d2d094
Update com.unity.multiplayer.mlapi/Runtime/Core/NetworkObject.cs
NoelStephensUnity e67a4c2
Merge branch 'develop' into refactor/mtt640-sceneobjects
NoelStephensUnity 34c07f3
Merge branch 'refactor/mtt640-sceneobjects' of https://github.com/Uni…
NoelStephensUnity 36b692f
refactor: Naming updates, comments, an d logic
NoelStephensUnity d232557
test: NetworkObject scene serialization test
NoelStephensUnity be9e635
refactor test
NoelStephensUnity 750b2bb
style
NoelStephensUnity e9137ae
style: invalidNetworkObjectFrequency
NoelStephensUnity cd956cb
style: spelling
NoelStephensUnity File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,6 +8,7 @@ | |
| using MLAPI.Logging; | ||
| using MLAPI.Serialization.Pooled; | ||
| using MLAPI.Transports; | ||
| using MLAPI.Serialization; | ||
| using UnityEngine; | ||
|
|
||
| namespace MLAPI | ||
|
|
@@ -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 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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; | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.