diff --git a/Assets/Scripts/NetworkManager.asset b/Assets/Scripts/NetworkManager.asset index 2afc161..47fb49e 100644 --- a/Assets/Scripts/NetworkManager.asset +++ b/Assets/Scripts/NetworkManager.asset @@ -43,7 +43,7 @@ MonoBehaviour: Data: - Name: Entry: 12 - Data: 18 + Data: 19 - Name: Entry: 7 Data: @@ -421,16 +421,70 @@ MonoBehaviour: Data: - Name: $k Entry: 1 - Data: buffer + Data: fullSyncInQueue - Name: $v Entry: 7 Data: 22|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 - Data: buffer + Data: fullSyncInQueue - Name: k__BackingField Entry: 7 Data: 23|System.RuntimeType, mscorlib + - Name: + Entry: 1 + Data: System.Boolean, mscorlib + - Name: + Entry: 8 + Data: + - Name: k__BackingField + Entry: 9 + Data: 23 + - Name: k__BackingField + Entry: 7 + Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib + - Name: + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: k__BackingField + Entry: 5 + Data: false + - Name: _fieldAttributes + Entry: 7 + Data: 24|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + - Name: + Entry: 12 + Data: 0 + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 1 + Data: buffer + - Name: $v + Entry: 7 + Data: 25|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: k__BackingField + Entry: 1 + Data: buffer + - Name: k__BackingField + Entry: 7 + Data: 26|System.RuntimeType, mscorlib - Name: Entry: 1 Data: System.Byte[][], mscorlib @@ -439,7 +493,7 @@ MonoBehaviour: Data: - Name: k__BackingField Entry: 7 - Data: 24|System.RuntimeType, mscorlib + Data: 27|System.RuntimeType, mscorlib - Name: Entry: 1 Data: System.Object[], mscorlib @@ -460,7 +514,7 @@ MonoBehaviour: Data: false - Name: _fieldAttributes Entry: 7 - Data: 25|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + Data: 28|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib - Name: Entry: 12 Data: 0 @@ -484,7 +538,7 @@ MonoBehaviour: Data: bufferIndex - Name: $v Entry: 7 - Data: 26|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + Data: 29|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 Data: bufferIndex @@ -508,7 +562,7 @@ MonoBehaviour: Data: false - Name: _fieldAttributes Entry: 7 - Data: 27|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + Data: 30|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib - Name: Entry: 12 Data: 0 @@ -532,13 +586,13 @@ MonoBehaviour: Data: networkedData - Name: $v Entry: 7 - Data: 28|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + Data: 31|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 Data: networkedData - Name: k__BackingField Entry: 7 - Data: 29|System.RuntimeType, mscorlib + Data: 32|System.RuntimeType, mscorlib - Name: Entry: 1 Data: System.Byte[], mscorlib @@ -547,7 +601,7 @@ MonoBehaviour: Data: - Name: k__BackingField Entry: 9 - Data: 29 + Data: 32 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -562,13 +616,13 @@ MonoBehaviour: Data: false - Name: _fieldAttributes Entry: 7 - Data: 30|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + Data: 33|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib - Name: Entry: 12 Data: 1 - Name: Entry: 7 - Data: 31|UdonSharp.UdonSyncedAttribute, UdonSharp.Runtime + Data: 34|UdonSharp.UdonSyncedAttribute, UdonSharp.Runtime - Name: Entry: 8 Data: @@ -590,72 +644,18 @@ MonoBehaviour: - Name: $k Entry: 1 Data: k__BackingField - - Name: $v - Entry: 7 - Data: 32|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - - Name: k__BackingField - Entry: 1 - Data: k__BackingField - - Name: k__BackingField - Entry: 7 - Data: 33|System.RuntimeType, mscorlib - - Name: - Entry: 1 - Data: System.Boolean, mscorlib - - Name: - Entry: 8 - Data: - - Name: k__BackingField - Entry: 9 - Data: 33 - - Name: k__BackingField - Entry: 7 - Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib - - Name: - Entry: 6 - Data: - - Name: - Entry: 8 - Data: - - Name: k__BackingField - Entry: 5 - Data: false - - Name: _fieldAttributes - Entry: 7 - Data: 34|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib - - Name: - Entry: 12 - Data: 0 - - Name: - Entry: 13 - Data: - - Name: - Entry: 8 - Data: - - Name: - Entry: 8 - Data: - - Name: - Entry: 8 - Data: - - Name: - Entry: 7 - Data: - - Name: $k - Entry: 1 - Data: k__BackingField - Name: $v Entry: 7 Data: 35|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 - Data: k__BackingField + Data: k__BackingField - Name: k__BackingField Entry: 9 - Data: 33 + Data: 23 - Name: k__BackingField Entry: 9 - Data: 33 + Data: 23 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -691,19 +691,19 @@ MonoBehaviour: Data: - Name: $k Entry: 1 - Data: k__BackingField + Data: k__BackingField - Name: $v Entry: 7 Data: 37|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 - Data: k__BackingField + Data: k__BackingField - Name: k__BackingField Entry: 9 - Data: 8 + Data: 23 - Name: k__BackingField Entry: 9 - Data: 8 + Data: 23 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -739,13 +739,13 @@ MonoBehaviour: Data: - Name: $k Entry: 1 - Data:
k__BackingField + Data: k__BackingField - Name: $v Entry: 7 Data: 39|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 - Data:
k__BackingField + Data: k__BackingField - Name: k__BackingField Entry: 9 Data: 8 @@ -787,19 +787,19 @@ MonoBehaviour: Data: - Name: $k Entry: 1 - Data: k__BackingField + Data:
k__BackingField - Name: $v Entry: 7 Data: 41|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 - Data: k__BackingField + Data:
k__BackingField - Name: k__BackingField Entry: 9 - Data: 33 + Data: 8 - Name: k__BackingField Entry: 9 - Data: 33 + Data: 8 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -835,19 +835,19 @@ MonoBehaviour: Data: - Name: $k Entry: 1 - Data: k__BackingField + Data: k__BackingField - Name: $v Entry: 7 Data: 43|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 - Data: k__BackingField + Data: k__BackingField - Name: k__BackingField Entry: 9 - Data: 33 + Data: 23 - Name: k__BackingField Entry: 9 - Data: 33 + Data: 23 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -883,19 +883,19 @@ MonoBehaviour: Data: - Name: $k Entry: 1 - Data: indexAtLastSerialization + Data: k__BackingField - Name: $v Entry: 7 Data: 45|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 - Data: indexAtLastSerialization + Data: k__BackingField - Name: k__BackingField Entry: 9 - Data: 20 + Data: 23 - Name: k__BackingField Entry: 9 - Data: 20 + Data: 23 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -931,16 +931,64 @@ MonoBehaviour: Data: - Name: $k Entry: 1 - Data: DebugImageToIndicateOwner + Data: indexAtLastSerialization - Name: $v Entry: 7 Data: 47|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: k__BackingField + Entry: 1 + Data: indexAtLastSerialization + - Name: k__BackingField + Entry: 9 + Data: 20 + - Name: k__BackingField + Entry: 9 + Data: 20 + - Name: k__BackingField + Entry: 7 + Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib + - Name: + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: k__BackingField + Entry: 5 + Data: false + - Name: _fieldAttributes + Entry: 7 + Data: 48|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + - Name: + Entry: 12 + Data: 0 + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 1 + Data: DebugImageToIndicateOwner + - Name: $v + Entry: 7 + Data: 49|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 Data: DebugImageToIndicateOwner - Name: k__BackingField Entry: 7 - Data: 48|System.RuntimeType, mscorlib + Data: 50|System.RuntimeType, mscorlib - Name: Entry: 1 Data: UnityEngine.Animator, UnityEngine.AnimationModule @@ -949,7 +997,7 @@ MonoBehaviour: Data: - Name: k__BackingField Entry: 9 - Data: 48 + Data: 50 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -964,13 +1012,13 @@ MonoBehaviour: Data: true - Name: _fieldAttributes Entry: 7 - Data: 49|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + Data: 51|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib - Name: Entry: 12 Data: 1 - Name: Entry: 7 - Data: 50|UnityEngine.SerializeField, UnityEngine.CoreModule + Data: 52|UnityEngine.SerializeField, UnityEngine.CoreModule - Name: Entry: 8 Data: diff --git a/Assets/Scripts/NetworkManager.cs b/Assets/Scripts/NetworkManager.cs index 94dca9e..1099301 100644 --- a/Assets/Scripts/NetworkManager.cs +++ b/Assets/Scripts/NetworkManager.cs @@ -21,6 +21,7 @@ namespace Marro.PacManUdon FullSync = 0, PacManTurn = 1, } + public class NetworkManager : UdonSharpBehaviour { // The network manager works by serializing event and state data into a byte array, including a timestamp for each event. @@ -70,10 +71,6 @@ namespace Marro.PacManUdon /// The total length of the header of an event, in bytes. /// private const ushort HeaderLength = 8; - /// - /// The amount of parts of which the header consists. - /// - private const ushort HeaderPartsCount = 4; /// /// The delay at which the receiving side replays events. @@ -115,6 +112,11 @@ namespace Marro.PacManUdon /// private int retriesWithoutSuccess; + /// + /// True if there is a full sync in the queue and we are not currently synced. + /// + private bool fullSyncInQueue; + /// /// Main buffer of data to be transmitted or processed /// @@ -155,7 +157,7 @@ namespace Marro.PacManUdon /// /// Is the current simulation to prepare for applying a network event? /// True = Yes, This update is preparing for a network update. - /// False = No, this update is after the network update or there was no + /// False = No, this update is after the network update or there was no network update this cycle. /// public bool IsEventUpdate { get; private set; } @@ -188,6 +190,7 @@ namespace Marro.PacManUdon retriesWithoutSuccess = 0; lastEventTimestamp = 0; lastEventId = 0; + fullSyncInQueue = false; offsetTime = Time.fixedTime; internalTime = 0; @@ -262,7 +265,7 @@ namespace Marro.PacManUdon private void SetOwner(bool isOwner) { - this.IsOwner = isOwner; + IsOwner = isOwner; if (DebugImageToIndicateOwner != null) { @@ -313,7 +316,7 @@ namespace Marro.PacManUdon var eventSizeBytes = BitConverter.GetBytes((ushort)eventSize); Array.Copy(eventSizeBytes, 0, result, HeaderEventSizeIndex, eventSizeBytes.Length); - AppendEventToBuffer(result); + QueueEventInBuffer(result); Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Prepared event with {eventSize} bytes and timestamp {timestamp} for serialization, index went from {oldIndex} to {this.bufferIndex}"); @@ -419,62 +422,61 @@ namespace Marro.PacManUdon var @event = GetArrayPart(networkedData, index, eventSize); var eventType = GetEventTypeFromHeader(@event); - - if (eventType == NetworkEventType.FullSync) - { - ProcessIncomingFullSync(@event); // Immediately process full sync - continue; - } - - if (!Synced) - { - Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Received event of type {eventType} while we are not yet synced to the remote time, ignoring event."); - continue; - } - var timestamp = GetTimestampFromHeader(@event); var eventId = GetEventIdFromHeader(@event); - if (timestamp == lastEventTimestamp + if (Synced || fullSyncInQueue) + { + if (timestamp == lastEventTimestamp && eventId == lastEventId) - { - Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Duplicate message of type {eventType}, timestamp: {timestamp}, messageId: {eventId}."); - continue; - } + { + Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Duplicate message of type {eventType}, timestamp: {timestamp}, messageId: {eventId}."); + continue; + } - if (eventId != GetNextEventId(lastEventId)) - { - Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) EventIds were not sequential! Did we miss a serialization? Timestamp: {timestamp}, eventId: {eventId}, lastEventId: {lastEventId}."); - HandleError(false); - return; - } + if (eventId != GetNextEventId(lastEventId)) + { + Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) EventIds were not sequential! Did we miss a serialization? Timestamp: {timestamp}, eventId: {eventId}, lastEventId: {lastEventId}."); + HandleError(false); + return; + } - AppendEventToBuffer(@event); + QueueEventInBuffer(@event); + } + else + { + // If we're not yet synced, we only care about full sync events. + if (eventType == NetworkEventType.FullSync) + { + QueueFullSyncInBuffer(@event); // Immediately process full sync + } + } lastEventTimestamp = timestamp; lastEventId = eventId; } - UpdateNextEventTime(); + if (Synced) + { + UpdateNextEventTime(); + } } - private void ProcessIncomingFullSync(byte[] @event) + private void QueueFullSyncInBuffer(byte[] @event) { // Intentionally not doing a buffer size check here, since this is not appended to the buffer // (and there is no good way to continue if this event is too large) // Clear buffer and put the full sync into it ClearBuffer(); - AppendEventToBuffer(@event); + QueueEventInBuffer(@event); - // Sync up to the time in the full sync - var timestamp = GetTimestampFromHeader(@event); - var eventId = GetEventIdFromHeader(@event); - SyncToTimestamp(timestamp, eventId); + // Set this event to play after the default delay + nextEventTime = internalTime + Delay; - // Immediately apply the full sync - UpdateNextEventTime(ignoreOrder: true); - Synced = true; + fullSyncInQueue = true; + + Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Queued full sync in buffer, should execute at {nextEventTime}."); } private void ProgressEventTime() @@ -483,17 +485,22 @@ namespace Marro.PacManUdon while (bufferIndex != 0 && nextEventTime <= internalTime) { - ProcessIncomingEvent(); + PerformEvent(buffer[0]); + DequeueEventsFromBuffer(1); UpdateNextEventTime(); } } - private void ProcessIncomingEvent() + private void PerformEvent(byte[] @event) { - var @event = NextEvent; - var timestamp = GetTimestampFromHeader(@event); var eventType = GetEventTypeFromHeader(@event); + + if (eventType == NetworkEventType.FullSync) + { + SyncToTimestamp(timestamp, GetEventIdFromHeader(@event)); + } + var index = (int)HeaderLength; // Skip header ProgressSyncedTime(timestamp); @@ -523,7 +530,11 @@ namespace Marro.PacManUdon return; } - RemoveProcessedDataFromBuffer(1); + if (!Synced && eventType == NetworkEventType.FullSync) + { + fullSyncInQueue = false; + Synced = true; + } Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Processed incoming event! Total {index} bytes."); @@ -538,15 +549,15 @@ namespace Marro.PacManUdon bufferIndex = 0; } - private void RemoveProcessedDataFromBuffer(int amountProcessed) + private void DequeueEventsFromBuffer(int eventCount) { var oldBuffer = buffer; - bufferIndex -= amountProcessed; + bufferIndex -= eventCount; buffer = new byte[BufferMaxTotalEvents][]; - Array.Copy(oldBuffer, amountProcessed, buffer, 0, bufferIndex); + Array.Copy(oldBuffer, eventCount, buffer, 0, bufferIndex); } - private bool AppendEventToBuffer(byte[] @event) + private bool QueueEventInBuffer(byte[] @event) { if (bufferIndex >= BufferMaxTotalEvents) { @@ -559,9 +570,6 @@ namespace Marro.PacManUdon return true; } - private byte[] NextEvent => - buffer[0]; - #endregion #region Time @@ -581,28 +589,28 @@ namespace Marro.PacManUdon private void SyncToTimestamp(float timestamp, byte eventId) { var oldOffset = offsetTime; - var timeToSyncTo = timestamp - Delay; - offsetTime = Time.fixedTime - timeToSyncTo; + offsetTime = Time.fixedTime - timestamp; var delta = offsetTime - oldOffset; - internalTime = internalTime - delta; - SyncedTime = SyncedTime - delta; + internalTime -= delta; + SyncedTime -= delta; + nextEventTime -= delta; lastEventTimestamp = timestamp; lastEventId = eventId; - Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Synced to timestamp {timestamp}, current time is {Time.fixedTime}, timeToSyncTo is {timeToSyncTo}, offsetTime is now {offsetTime}, internalTime is now {internalTime}, SyncedTime is now {SyncedTime}"); + Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Synced to timestamp {timestamp}, current time is {Time.fixedTime}, offsetTime is now {offsetTime}, internalTime is now {internalTime}, SyncedTime is now {SyncedTime}, nextEventTime is now {nextEventTime}"); } - private void UpdateNextEventTime(bool ignoreOrder = false) + private void UpdateNextEventTime() { if (bufferIndex == 0) { return; } - var nextEventTime = GetTimestampFromHeader(NextEvent); - if (ignoreOrder || nextEventTime >= this.nextEventTime) + var nextEventTime = GetTimestampFromHeader(buffer[0]); + if (nextEventTime >= this.nextEventTime) { this.nextEventTime = nextEventTime; } @@ -698,7 +706,7 @@ namespace Marro.PacManUdon Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Serialized with {networkedData.Length} bytes!\nBytes sent:\n{BytesToString(networkedData)}"); // Remove all transferred data from the buffer, leaving data that came in after serialization - RemoveProcessedDataFromBuffer(indexAtLastSerialization); + DequeueEventsFromBuffer(indexAtLastSerialization); networkedData = new byte[0]; } @@ -774,6 +782,8 @@ namespace Marro.PacManUdon debugOutput.text += $"{nameof(NetworkManager)}:\n" + $"IsOwner: {IsOwner}\n" + $"Ready: {Ready}\n" + + $"Synced: {Synced}\n" + + $"fullSyncInQueue: {fullSyncInQueue}\n" + $"Time.fixedTime: {Time.fixedTime}\n" + $"offsetTime: {offsetTime}\n" + $"internalTime: {internalTime}\n" + diff --git a/Assets/Test stuff/TestBall.cs b/Assets/Test stuff/TestBall.cs index 48f7380..5043834 100644 --- a/Assets/Test stuff/TestBall.cs +++ b/Assets/Test stuff/TestBall.cs @@ -40,11 +40,16 @@ public class TestBall : SyncedObject public void Initialize(NetworkManager networkManager) { this.networkManager = networkManager; + sumOfDt = networkManager.SyncedTime; + + amountUp = 0; + loopOffset = 0; + jumps = new float[10]; jumpsIndex = 0; } - + public override void SyncedUpdate() { SetProgress(GetProgress()); // A quick test that these methods work correctly