diff --git a/Assets/Scripts/NetworkManager.asset b/Assets/Scripts/NetworkManager.asset index 45681d1..2896d9f 100644 --- a/Assets/Scripts/NetworkManager.asset +++ b/Assets/Scripts/NetworkManager.asset @@ -169,19 +169,25 @@ MonoBehaviour: Data: - Name: $k Entry: 1 - Data: isSynced + Data: offsetTime - Name: $v Entry: 7 Data: 10|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 - Data: isSynced + Data: offsetTime - Name: k__BackingField - Entry: 9 - Data: 8 + Entry: 7 + Data: 11|System.RuntimeType, mscorlib + - Name: + Entry: 1 + Data: System.Single, mscorlib + - Name: + Entry: 8 + Data: - Name: k__BackingField Entry: 9 - Data: 8 + Data: 11 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -196,7 +202,7 @@ MonoBehaviour: Data: false - Name: _fieldAttributes Entry: 7 - Data: 11|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + Data: 12|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib - Name: Entry: 12 Data: 0 @@ -217,25 +223,19 @@ MonoBehaviour: Data: - Name: $k Entry: 1 - Data: offsetTime + Data: internalTime - Name: $v Entry: 7 - Data: 12|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + Data: 13|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 - Data: offsetTime + Data: internalTime - Name: k__BackingField - Entry: 7 - Data: 13|System.RuntimeType, mscorlib - - Name: - Entry: 1 - Data: System.Single, mscorlib - - Name: - Entry: 8 - Data: + Entry: 9 + Data: 11 - Name: k__BackingField Entry: 9 - Data: 13 + Data: 11 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -271,19 +271,19 @@ MonoBehaviour: Data: - Name: $k Entry: 1 - Data: internalTime + Data: nextEventTime - Name: $v Entry: 7 Data: 15|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 - Data: internalTime + Data: nextEventTime - Name: k__BackingField Entry: 9 - Data: 13 + Data: 11 - Name: k__BackingField Entry: 9 - Data: 13 + Data: 11 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -319,19 +319,19 @@ MonoBehaviour: Data: - Name: $k Entry: 1 - Data: nextEventTime + Data: lastEventTimestamp - Name: $v Entry: 7 Data: 17|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 - Data: nextEventTime + Data: lastEventTimestamp - Name: k__BackingField Entry: 9 - Data: 13 + Data: 11 - Name: k__BackingField Entry: 9 - Data: 13 + Data: 11 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -367,19 +367,19 @@ MonoBehaviour: Data: - Name: $k Entry: 1 - Data: lastEventTimestamp + Data: lastEventId - Name: $v Entry: 7 Data: 19|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 - Data: lastEventTimestamp + Data: lastEventId - Name: k__BackingField Entry: 7 Data: 20|System.RuntimeType, mscorlib - Name: Entry: 1 - Data: System.UInt32, mscorlib + Data: System.Byte, mscorlib - Name: Entry: 8 Data: @@ -421,19 +421,19 @@ MonoBehaviour: Data: - Name: $k Entry: 1 - Data: lastEventId + Data: retriesWithoutSuccess - Name: $v Entry: 7 Data: 22|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 - Data: lastEventId + Data: retriesWithoutSuccess - Name: k__BackingField Entry: 7 Data: 23|System.RuntimeType, mscorlib - Name: Entry: 1 - Data: System.Byte, mscorlib + Data: System.Int32, mscorlib - Name: Entry: 8 Data: @@ -475,70 +475,16 @@ MonoBehaviour: Data: - Name: $k Entry: 1 - Data: retriesWithoutSuccess + Data: buffer - Name: $v Entry: 7 Data: 25|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 - Data: retriesWithoutSuccess + Data: buffer - Name: k__BackingField Entry: 7 Data: 26|System.RuntimeType, mscorlib - - Name: - Entry: 1 - Data: System.Int32, mscorlib - - Name: - Entry: 8 - Data: - - Name: k__BackingField - Entry: 9 - Data: 26 - - 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: 27|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: 28|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - - Name: k__BackingField - Entry: 1 - Data: buffer - - Name: k__BackingField - Entry: 7 - Data: 29|System.RuntimeType, mscorlib - Name: Entry: 1 Data: System.Byte[][], mscorlib @@ -547,7 +493,7 @@ MonoBehaviour: Data: - Name: k__BackingField Entry: 7 - Data: 30|System.RuntimeType, mscorlib + Data: 27|System.RuntimeType, mscorlib - Name: Entry: 1 Data: System.Object[], mscorlib @@ -568,7 +514,7 @@ MonoBehaviour: Data: false - Name: _fieldAttributes Entry: 7 - Data: 31|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 @@ -592,16 +538,16 @@ MonoBehaviour: Data: bufferIndex - Name: $v Entry: 7 - Data: 32|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + Data: 29|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 Data: bufferIndex - Name: k__BackingField Entry: 9 - Data: 26 + Data: 23 - Name: k__BackingField Entry: 9 - Data: 26 + Data: 23 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -616,7 +562,7 @@ MonoBehaviour: Data: false - Name: _fieldAttributes Entry: 7 - Data: 33|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 @@ -640,13 +586,13 @@ MonoBehaviour: Data: networkedData - Name: $v Entry: 7 - Data: 34|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: 35|System.RuntimeType, mscorlib + Data: 32|System.RuntimeType, mscorlib - Name: Entry: 1 Data: System.Byte[], mscorlib @@ -655,7 +601,7 @@ MonoBehaviour: Data: - Name: k__BackingField Entry: 9 - Data: 35 + Data: 32 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -670,13 +616,13 @@ MonoBehaviour: Data: false - Name: _fieldAttributes Entry: 7 - Data: 36|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: 37|UdonSharp.UdonSyncedAttribute, UdonSharp.Runtime + Data: 34|UdonSharp.UdonSyncedAttribute, UdonSharp.Runtime - Name: Entry: 8 Data: @@ -700,7 +646,7 @@ MonoBehaviour: Data: k__BackingField - Name: $v Entry: 7 - Data: 38|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + Data: 35|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 Data: k__BackingField @@ -724,7 +670,55 @@ MonoBehaviour: Data: false - Name: _fieldAttributes Entry: 7 - Data: 39|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + Data: 36|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: 37|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: k__BackingField + Entry: 1 + Data: k__BackingField + - Name: k__BackingField + Entry: 9 + Data: 8 + - Name: k__BackingField + Entry: 9 + Data: 8 + - 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: 38|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib - Name: Entry: 12 Data: 0 @@ -748,16 +742,16 @@ MonoBehaviour: Data: k__BackingField - Name: $v Entry: 7 - Data: 40|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + Data: 39|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 Data: k__BackingField - Name: k__BackingField Entry: 9 - Data: 13 + Data: 11 - Name: k__BackingField Entry: 9 - Data: 13 + Data: 11 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -772,7 +766,7 @@ MonoBehaviour: Data: false - Name: _fieldAttributes Entry: 7 - Data: 41|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + Data: 40|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib - Name: Entry: 12 Data: 0 @@ -796,16 +790,16 @@ MonoBehaviour: Data:
k__BackingField - Name: $v Entry: 7 - Data: 42|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + Data: 41|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 Data:
k__BackingField - Name: k__BackingField Entry: 9 - Data: 13 + Data: 11 - Name: k__BackingField Entry: 9 - Data: 13 + Data: 11 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -820,7 +814,7 @@ MonoBehaviour: Data: false - Name: _fieldAttributes Entry: 7 - Data: 43|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + Data: 42|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib - Name: Entry: 12 Data: 0 @@ -844,7 +838,7 @@ MonoBehaviour: Data: k__BackingField - Name: $v Entry: 7 - Data: 44|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + Data: 43|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 Data: k__BackingField @@ -868,7 +862,7 @@ MonoBehaviour: Data: false - Name: _fieldAttributes Entry: 7 - Data: 45|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + Data: 44|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib - Name: Entry: 12 Data: 0 @@ -892,16 +886,16 @@ MonoBehaviour: Data: indexAtLastSerialization - Name: $v Entry: 7 - Data: 46|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + Data: 45|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 Data: indexAtLastSerialization - Name: k__BackingField Entry: 9 - Data: 26 + Data: 23 - Name: k__BackingField Entry: 9 - Data: 26 + Data: 23 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -916,7 +910,7 @@ MonoBehaviour: Data: false - Name: _fieldAttributes Entry: 7 - Data: 47|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + Data: 46|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib - Name: Entry: 12 Data: 0 @@ -940,13 +934,13 @@ MonoBehaviour: Data: DebugImageToIndicateOwner - Name: $v Entry: 7 - Data: 48|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + Data: 47|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 Data: DebugImageToIndicateOwner - Name: k__BackingField Entry: 7 - Data: 49|System.RuntimeType, mscorlib + Data: 48|System.RuntimeType, mscorlib - Name: Entry: 1 Data: UnityEngine.Animator, UnityEngine.AnimationModule @@ -955,7 +949,7 @@ MonoBehaviour: Data: - Name: k__BackingField Entry: 9 - Data: 49 + Data: 48 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -970,13 +964,13 @@ MonoBehaviour: Data: true - Name: _fieldAttributes Entry: 7 - Data: 50|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + Data: 49|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib - Name: Entry: 12 Data: 1 - Name: Entry: 7 - Data: 51|UnityEngine.SerializeField, UnityEngine.CoreModule + Data: 50|UnityEngine.SerializeField, UnityEngine.CoreModule - Name: Entry: 8 Data: diff --git a/Assets/Scripts/NetworkManager.cs b/Assets/Scripts/NetworkManager.cs index ec7a283..9459c21 100644 --- a/Assets/Scripts/NetworkManager.cs +++ b/Assets/Scripts/NetworkManager.cs @@ -28,8 +28,10 @@ namespace Marro.PacManUdon // If user is not owner, this data is read into the same buffer and replayed based on the included timestamp. // Data replay is delayed with an offset on the timestamp to hide inconsistency in latency. - // The timestamp is transferred in ms as a 32 bit uint, which gives a maximum time of about 49 days. - // The maximum allowed age of a VRChat instance is 7 days, so this should not cause issues. + // Each event contains a header. The first part contains the size of the event as a ushort, allowing a maximum size of 65,536 bytes. + // After that timestamp is transferred in seconds since the owner started the game as a float, matching Unity's time representation. + // Afterwards is a message id, a single byte which increments (with overflow) for every event to confirm data completeness. + // Lastly, a single byte indicates the type of event. 0 is a full sync, which is reserved for syncing up from any unknown state. // A byte array is used as a DataList or DataDictionary can only be transmitted as JSON which is much less efficient. // As Udon does not support instantiating objects, I have not created classes to represent the data being sent. @@ -37,7 +39,7 @@ namespace Marro.PacManUdon // An event has the following structure: // [0-1]: (ushort) Size of event. - // [2-5]: (uint) Time in seconds at which event occured. + // [2-5]: (float) Time in seconds at which event occured. // [6]: (byte) Message id, increments by one for each message with the same timestamp. // [7]: (byte) Type of event. 0 = Full Sync, which is used to sync up from an undefinted state. // [+]: Event-specific data. @@ -73,14 +75,6 @@ namespace Marro.PacManUdon /// private const ushort HeaderPartsCount = 4; - /// - /// The multiplier from Unity time to a timestamp. - /// - private const int TimestampMultiplier = 1000; - /// - /// The zero value of a timestamp. Anything below this value is negative. - /// - private const uint TimestampZeroValue = 10000; /// /// The delay at which the receiving side replays events. /// @@ -120,7 +114,7 @@ namespace Marro.PacManUdon /// /// The timestamp of the most recent event created or received. /// - private uint lastEventTimestamp; + private float lastEventTimestamp; /// /// The message id of the most recent event created or received. /// @@ -290,7 +284,7 @@ namespace Marro.PacManUdon return; } - var timestamp = TimeToTimestamp(SyncedTime); + var timestamp = SyncedTime; var eventId = GetNextEventId(lastEventId); @@ -330,7 +324,7 @@ namespace Marro.PacManUdon retriesWithoutSuccess = 0; // We had success! } - private static void InitializeEvent(NetworkEventType eventType, uint timestamp, byte eventId, int maxSize, out byte[][] data, out int index) + private static void InitializeEvent(NetworkEventType eventType, float timestamp, byte eventId, int maxSize, out byte[][] data, out int index) { // Create header var timestampBytes = BitConverter.GetBytes(timestamp); @@ -573,10 +567,10 @@ namespace Marro.PacManUdon SyncedTime = newTime; } - private void SyncToTimestamp(uint timestamp, byte eventId) + private void SyncToTimestamp(float timestamp, byte eventId) { var oldOffset = offsetTime; - var timeToSyncTo = TimestampToTime(timestamp) - Delay; + var timeToSyncTo = timestamp - Delay; offsetTime = Time.fixedTime - timeToSyncTo; var delta = offsetTime - oldOffset; @@ -596,7 +590,7 @@ namespace Marro.PacManUdon return; } - var nextEventTime = TimestampToTime(GetTimestampFromHeader(NextEvent)); + var nextEventTime = GetTimestampFromHeader(NextEvent); if (ignoreOrder || nextEventTime >= this.nextEventTime) { this.nextEventTime = nextEventTime; @@ -608,16 +602,6 @@ namespace Marro.PacManUdon return; } } - - public static uint TimeToTimestamp(float time) - { - return (uint)((time * TimestampMultiplier) + TimestampZeroValue); - } - - public static float TimestampToTime(uint timeStamp) - { - return (timeStamp - (long)TimestampZeroValue) / (float)TimestampMultiplier; // Use a long here to prevent an underflow - } #endregion #region Header @@ -639,8 +623,8 @@ namespace Marro.PacManUdon public static NetworkEventType GetEventTypeFromHeader(byte[] @event, int eventIndex = 0) => (NetworkEventType)@event[eventIndex + HeaderEventTypeIndex]; - public static uint GetTimestampFromHeader(byte[] @event, int eventIndex = 0) => - BitConverter.ToUInt32(@event, eventIndex + HeaderTimestampIndex); + public static float GetTimestampFromHeader(byte[] @event, int eventIndex = 0) => + BitConverter.ToSingle(@event, eventIndex + HeaderTimestampIndex); public static byte GetEventIdFromHeader(byte[] @event, int eventIndex = 0) => @event[eventIndex + HeaderEventIdIndex]; @@ -764,7 +748,7 @@ namespace Marro.PacManUdon #endregion #region Debug - public void SimulateSyncToTimestamp(uint timestamp) + public void SimulateSyncToTimestamp(float timestamp) { SyncToTimestamp(timestamp, 0); } diff --git a/Assets/Test stuff/TestBall.asset b/Assets/Test stuff/TestBall.asset index 7bcf97a..9092266 100644 --- a/Assets/Test stuff/TestBall.asset +++ b/Assets/Test stuff/TestBall.asset @@ -400,10 +400,10 @@ MonoBehaviour: Data: loopOffset - Name: k__BackingField Entry: 9 - Data: 11 + Data: 19 - Name: k__BackingField Entry: 9 - Data: 11 + Data: 19 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib diff --git a/Assets/Test stuff/TestBall.cs b/Assets/Test stuff/TestBall.cs index fa870b1..c45fe62 100644 --- a/Assets/Test stuff/TestBall.cs +++ b/Assets/Test stuff/TestBall.cs @@ -24,15 +24,15 @@ public class TestBall : SyncedObject private NetworkManager networkManager; - private const int LoopTimeMs = 1000; + private const float LoopTime = 1f; private const float MaxUp = 0.7f; private const float UpPerPress = 0.4f; - private const float DownPerSecond = 1; + private const float DownPerSecond = 1f; private float sumOfDt; private float amountUp = 0; - private int loopOffset = 0; + private float loopOffset = 0; private float[] jumps; private int jumpsIndex; @@ -78,25 +78,25 @@ public class TestBall : SyncedObject private void SetProgress(float progress) { var currentTimestamp = GetCurrentTimestamp(); - loopOffset = (int)(currentTimestamp - progress * LoopTimeMs); + loopOffset = currentTimestamp - progress * LoopTime; } private float GetProgress() { var currentTimestamp = GetCurrentTimestamp(); //Debug.Log($"CurrentTimeStamp for mode {mode}: {currentTimestamp}"); - return ((int)currentTimestamp - loopOffset) % LoopTimeMs / (float)LoopTimeMs; // "uint % int" is not exposed, I love working in Udon + return currentTimestamp - loopOffset % LoopTime / LoopTime; } - private uint GetCurrentTimestamp() + private float GetCurrentTimestamp() { switch (mode) { case TestBallMode.UseNetworkTime: - return NetworkManager.TimeToTimestamp(networkManager.SyncedTime); + return networkManager.SyncedTime; case TestBallMode.UseNetworkDt: case TestBallMode.UseUnityDt: - return NetworkManager.TimeToTimestamp(sumOfDt); + return sumOfDt; default: Debug.LogError($"({nameof(TestBall)}) Unknown mode {mode}!"); return 0; diff --git a/Assets/Test stuff/TestBallManager.cs b/Assets/Test stuff/TestBallManager.cs index 828c899..e031823 100644 --- a/Assets/Test stuff/TestBallManager.cs +++ b/Assets/Test stuff/TestBallManager.cs @@ -56,7 +56,7 @@ public class TestBallManager : UdonSharpBehaviour { if (VRCPlayerApi.GetPlayerCount() == 1) { - networkManager.SimulateSyncToTimestamp(NetworkManager.TimeToTimestamp(networkManager.SyncedTime - 0.5f)); + networkManager.SimulateSyncToTimestamp(networkManager.SyncedTime - 0.5f); } else if (networkManager.IsOwner) {