Tools for testing
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using TMPro;
|
||||
using UdonSharp;
|
||||
@@ -52,9 +54,9 @@ namespace Marro.PacManUdon
|
||||
/// </summary>
|
||||
[SerializeField] private GameObject root;
|
||||
/// <summary>
|
||||
/// The delay at which the receiving side replays events.
|
||||
/// The delay in ticks at which the receiving side replays events.
|
||||
/// </summary>
|
||||
[SerializeField] private float delay = 1f;
|
||||
[SerializeField] private int delay = 50;
|
||||
/// <summary>
|
||||
/// The maximum amount of times a message is sent.
|
||||
/// </summary>
|
||||
@@ -62,11 +64,11 @@ namespace Marro.PacManUdon
|
||||
/// <summary>
|
||||
/// How long to wait since last message to send next ping.
|
||||
/// </summary>
|
||||
[SerializeField] private float pingDelay = 0.3f;
|
||||
[SerializeField] private int pingDelay = 15;
|
||||
/// <summary>
|
||||
/// The time delta at which updates occur.
|
||||
/// </summary>
|
||||
[SerializeField] private float updateDelta = 0.0166666667f;
|
||||
[SerializeField] private float tickDelta = 0.0166666667f;
|
||||
#endregion
|
||||
|
||||
#region Constants
|
||||
@@ -123,13 +125,14 @@ namespace Marro.PacManUdon
|
||||
private SyncedObject[] syncedUpdateSubscribers;
|
||||
|
||||
/// <summary>
|
||||
/// Offset from system time to network time, including delay.
|
||||
/// The <see cref="Time.fixedTime"/> that corresponds to tick 0.
|
||||
/// </summary>
|
||||
private float offsetTime;
|
||||
private float startTime;
|
||||
|
||||
/// <summary>
|
||||
/// Time since last full sync, captured when this FixedUpdate started, with network delay applied.
|
||||
/// Time in ticks since start of game.
|
||||
/// </summary>
|
||||
private float internalTime;
|
||||
private int targetTicks;
|
||||
|
||||
/// <summary>
|
||||
/// True if time is paused
|
||||
@@ -142,13 +145,9 @@ namespace Marro.PacManUdon
|
||||
private bool stepNext;
|
||||
|
||||
/// <summary>
|
||||
/// Time at which the next update should occur.
|
||||
/// Time at which next received event occured, in ticks.
|
||||
/// </summary>
|
||||
private float nextUpdateTime;
|
||||
/// <summary>
|
||||
/// Time at which next received event occured.
|
||||
/// </summary>
|
||||
private float nextEventTime;
|
||||
private int nextEventTime;
|
||||
|
||||
/// <summary>
|
||||
/// Amounot of retries in a row without a successful sync.
|
||||
@@ -196,9 +195,9 @@ namespace Marro.PacManUdon
|
||||
/// </summary>
|
||||
private int eventTransmissionHistoryIndex;
|
||||
/// <summary>
|
||||
/// Time of last event transmission.
|
||||
/// Time of last event transmission, in ticks.
|
||||
/// </summary>
|
||||
private float lastEventTransmissionTime;
|
||||
private int lastEventTransmissionTime;
|
||||
|
||||
|
||||
/// <summary>
|
||||
@@ -251,14 +250,18 @@ namespace Marro.PacManUdon
|
||||
private bool synced = false;
|
||||
|
||||
/// <summary>
|
||||
/// The time since last full sync which is currently being simulated.
|
||||
/// The time since start of game, in ticks.
|
||||
/// </summary>
|
||||
public int SyncedTimeTicks { get; private set; }
|
||||
/// <summary>
|
||||
/// The time since start of game which is currently being simulated.
|
||||
/// </summary>
|
||||
public float SyncedTime { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Time since the last simulation, in seconds.
|
||||
/// </summary>
|
||||
public float SyncedDeltaTime { get; private set; }
|
||||
public float SyncedDeltaTime => tickDelta;
|
||||
|
||||
/// <summary>
|
||||
/// Is the current simulation to prepare for applying a network event?
|
||||
@@ -355,11 +358,10 @@ namespace Marro.PacManUdon
|
||||
retriesWithoutSuccess = 0;
|
||||
hasFullSyncReady = false;
|
||||
|
||||
offsetTime = Time.fixedTime;
|
||||
internalTime = 0;
|
||||
targetTicks = 0;
|
||||
startTime = Time.fixedTime;
|
||||
SyncedTime = 0;
|
||||
SyncedDeltaTime = Time.fixedDeltaTime;
|
||||
nextUpdateTime = SyncedTime;
|
||||
SyncedTimeTicks = 0;
|
||||
|
||||
Ready = true;
|
||||
|
||||
@@ -373,11 +375,16 @@ namespace Marro.PacManUdon
|
||||
RequestEvent(NetworkEventType.FullSync);
|
||||
}
|
||||
|
||||
Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Initialized, time offset: {offsetTime}");
|
||||
Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Initialized");
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (debugOutput != null)
|
||||
{
|
||||
WriteDebugOutput(debugOutput);
|
||||
}
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
return;
|
||||
@@ -387,35 +394,12 @@ namespace Marro.PacManUdon
|
||||
UpdateInternalTime();
|
||||
|
||||
// Forwards simulated time by updateDelta until we're caught up
|
||||
while (nextUpdateTime <= internalTime)
|
||||
while (SyncedTimeTicks <= targetTicks)
|
||||
{
|
||||
PerformFixedSyncedUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateInternalTime()
|
||||
{
|
||||
var delta = Time.fixedTime - offsetTime - internalTime;
|
||||
|
||||
if (!paused)
|
||||
{
|
||||
// Continue time like normal
|
||||
internalTime += delta;
|
||||
}
|
||||
else if (paused && !stepNext)
|
||||
{
|
||||
// Since we're paused, increase our offset from Unity's time
|
||||
offsetTime += delta;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Step forward by exactly updateDelta, apply the remainder to our offset
|
||||
offsetTime += delta - updateDelta;
|
||||
internalTime += updateDelta;
|
||||
stepNext = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void PerformFixedSyncedUpdate()
|
||||
{
|
||||
if (Ready)
|
||||
@@ -431,9 +415,8 @@ namespace Marro.PacManUdon
|
||||
}
|
||||
}
|
||||
|
||||
ProgressSyncedTime(nextUpdateTime);
|
||||
ProgressSyncedTime();
|
||||
CallSyncedUpdate();
|
||||
nextUpdateTime = SyncedTime + updateDelta;
|
||||
}
|
||||
|
||||
private void CallSyncedUpdate()
|
||||
@@ -555,7 +538,7 @@ namespace Marro.PacManUdon
|
||||
return;
|
||||
}
|
||||
|
||||
var timestamp = SyncedTime;
|
||||
var timestamp = SyncedTimeTicks;
|
||||
|
||||
var eventId = GetNextEventId(lastEventId);
|
||||
|
||||
@@ -593,7 +576,7 @@ namespace Marro.PacManUdon
|
||||
retriesWithoutSuccess = 0; // We had success!
|
||||
}
|
||||
|
||||
private static void InitializeEvent(NetworkEventType eventType, float timestamp, byte eventId, out byte[] data, out int index)
|
||||
private static void InitializeEvent(NetworkEventType eventType, int timestamp, byte eventId, out byte[] data, out int index)
|
||||
{
|
||||
data = new byte[MaxEventSize];
|
||||
|
||||
@@ -640,7 +623,7 @@ namespace Marro.PacManUdon
|
||||
private void ProgressPingTime()
|
||||
{
|
||||
if (eventsQueueIndex > 0 && !serializationRequested
|
||||
&& internalTime - lastEventTransmissionTime >= pingDelay)
|
||||
&& targetTicks - lastEventTransmissionTime >= pingDelay)
|
||||
{
|
||||
RequestSerializationForEvents();
|
||||
}
|
||||
@@ -695,7 +678,7 @@ namespace Marro.PacManUdon
|
||||
// If there was a full sync in the queue, it has now been transmitted at least once
|
||||
hasFullSyncReady = false;
|
||||
|
||||
lastEventTransmissionTime = internalTime;
|
||||
lastEventTransmissionTime = targetTicks;
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -811,7 +794,7 @@ namespace Marro.PacManUdon
|
||||
QueueEventInBuffer(@event);
|
||||
|
||||
// Set this event to play after the default delay
|
||||
nextEventTime = internalTime + delay;
|
||||
nextEventTime = targetTicks + delay;
|
||||
|
||||
hasFullSyncReady = true;
|
||||
|
||||
@@ -822,7 +805,7 @@ namespace Marro.PacManUdon
|
||||
{
|
||||
IsEventUpdate = true;
|
||||
|
||||
while (eventsQueueIndex > 0 && nextEventTime <= SyncedTime)
|
||||
while (eventsQueueIndex > 0 && nextEventTime <= SyncedTimeTicks)
|
||||
{
|
||||
var success = ApplyEvent(eventsQueue[0]);
|
||||
|
||||
@@ -847,11 +830,16 @@ namespace Marro.PacManUdon
|
||||
{
|
||||
SyncToTimestamp(timestamp);
|
||||
}
|
||||
else if (timestamp < SyncedTimeTicks)
|
||||
{
|
||||
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Next received event is in the past! " +
|
||||
$"{nameof(nextEventTime)}: {nextEventTime} < {nameof(SyncedTimeTicks)}: {SyncedTimeTicks}.");
|
||||
HandleError(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
var index = (int)HeaderLength; // Skip header
|
||||
|
||||
ProgressSyncedTime(timestamp);
|
||||
|
||||
var subscribers = GetEventSubscribers(eventType);
|
||||
|
||||
Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) ApplyEvent with dt {SyncedDeltaTime}");
|
||||
@@ -890,7 +878,7 @@ namespace Marro.PacManUdon
|
||||
Synced = true;
|
||||
}
|
||||
|
||||
Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Performed incoming eventof type {eventType}! Total {index} bytes.");
|
||||
Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Performed incoming event of type {eventType}! Total {index} bytes.");
|
||||
|
||||
retriesWithoutSuccess = 0; // We had success!
|
||||
|
||||
@@ -951,30 +939,38 @@ namespace Marro.PacManUdon
|
||||
#endregion
|
||||
|
||||
#region Time
|
||||
private void ProgressSyncedTime(float newTime)
|
||||
private void UpdateInternalTime()
|
||||
{
|
||||
//Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) updating SyncedTime from {SyncedTime} to {newTime}");
|
||||
SyncedDeltaTime = newTime - SyncedTime;
|
||||
|
||||
if (SyncedDeltaTime < 0)
|
||||
if (paused && !stepNext)
|
||||
{
|
||||
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Negative Dt: {SyncedDeltaTime}! Going from {SyncedTime} to {newTime}, IsEventUpdate: {IsEventUpdate}");
|
||||
return;
|
||||
}
|
||||
|
||||
SyncedTime = newTime;
|
||||
if (paused && stepNext)
|
||||
{
|
||||
targetTicks++;
|
||||
stepNext = false;
|
||||
return;
|
||||
}
|
||||
|
||||
targetTicks = (int)((Time.fixedTime - startTime) / tickDelta);
|
||||
}
|
||||
|
||||
private void SyncToTimestamp(float timestamp)
|
||||
private void ProgressSyncedTime()
|
||||
{
|
||||
var oldOffset = offsetTime;
|
||||
offsetTime = Time.fixedTime - timestamp;
|
||||
SyncedTimeTicks++;
|
||||
SyncedTime = SyncedTimeTicks * tickDelta;
|
||||
}
|
||||
|
||||
var delta = offsetTime - oldOffset;
|
||||
internalTime -= delta;
|
||||
SyncedTime -= delta;
|
||||
nextEventTime -= delta;
|
||||
private void SyncToTimestamp(int timestamp)
|
||||
{
|
||||
startTime = Time.fixedTime - timestamp * tickDelta;
|
||||
targetTicks = timestamp;
|
||||
SyncedTimeTicks = timestamp;
|
||||
SyncedTime = SyncedTimeTicks * tickDelta;
|
||||
nextEventTime = timestamp;
|
||||
|
||||
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}");
|
||||
Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Synced to timestamp {timestamp}, internalTime is now {targetTicks}, SyncedTime is now {SyncedTime}, nextEventTime is now {nextEventTime}");
|
||||
}
|
||||
|
||||
private void UpdateNextEventTime()
|
||||
@@ -993,9 +989,9 @@ namespace Marro.PacManUdon
|
||||
return;
|
||||
}
|
||||
|
||||
if (nextEventTime < SyncedTime)
|
||||
if (nextEventTime < SyncedTimeTicks)
|
||||
{
|
||||
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) New event timestamp is earlier than our current synced time by {SyncedTime - nextEventTime} seconds! nextEventTime: {nextEventTime} SyncedTime: {SyncedTime}, internalTime: {internalTime}");
|
||||
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) New event timestamp is earlier than our current synced time by {SyncedTime - nextEventTime} seconds! nextEventTime: {nextEventTime} SyncedTime: {SyncedTime}, internalTime: {targetTicks}");
|
||||
HandleError(true);
|
||||
return;
|
||||
}
|
||||
@@ -1026,8 +1022,8 @@ namespace Marro.PacManUdon
|
||||
private static NetworkEventType GetEventTypeFromHeader(byte[] @event, int eventIndex = 0) =>
|
||||
(NetworkEventType)@event[eventIndex + HeaderEventTypeIndex];
|
||||
|
||||
private static float GetTimestampFromHeader(byte[] @event, int eventIndex = 0) =>
|
||||
BitConverter.ToSingle(@event, eventIndex + HeaderTimestampIndex);
|
||||
private static int GetTimestampFromHeader(byte[] @event, int eventIndex = 0) =>
|
||||
BitConverter.ToInt32(@event, eventIndex + HeaderTimestampIndex);
|
||||
|
||||
private static byte GetEventIdFromHeader(byte[] @event, int eventIndex = 0) =>
|
||||
@event[eventIndex + HeaderEventIdIndex];
|
||||
@@ -1107,6 +1103,11 @@ namespace Marro.PacManUdon
|
||||
Array.Copy(data, start, result, 0, length);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static float RoundDown(float value, float precision)
|
||||
{
|
||||
return (float)(Math.Floor(value / precision) * precision);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SyncedData
|
||||
@@ -1137,20 +1138,20 @@ namespace Marro.PacManUdon
|
||||
#region Debug
|
||||
public void SimulateSyncToTimestamp(float timestamp)
|
||||
{
|
||||
SyncToTimestamp(timestamp);
|
||||
//SyncToTimestamp(timestamp);
|
||||
}
|
||||
|
||||
public void WriteDebugOutput(TMP_InputField debugOutput)
|
||||
{
|
||||
debugOutput.text += $"{nameof(NetworkManager)}:\n" +
|
||||
debugOutput.text = $"{nameof(NetworkManager)}:\n" +
|
||||
$"IsOwner: {IsOwner}\n" +
|
||||
$"Ready: {Ready}\n" +
|
||||
$"Synced: {Synced}\n" +
|
||||
$"hasFullSyncReady: {hasFullSyncReady}\n" +
|
||||
$"lastEventId: {lastEventId}" +
|
||||
$"lastEventId: {lastEventId}\n" +
|
||||
$"Time.fixedTime: {Time.fixedTime}\n" +
|
||||
$"offsetTime: {offsetTime}\n" +
|
||||
$"internalTime: {internalTime}\n" +
|
||||
$"startTime: {startTime}\n" +
|
||||
$"targetTicks: {targetTicks}\n" +
|
||||
$"SyncedTime: {SyncedTime}\n" +
|
||||
$"Dt: {SyncedDeltaTime}\n" +
|
||||
$"BufferIndex: {eventsQueueIndex}\n" +
|
||||
@@ -1158,6 +1159,11 @@ namespace Marro.PacManUdon
|
||||
$"\n";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Text field to display debug info in.
|
||||
/// </summary>
|
||||
[SerializeField] private TMP_InputField debugOutput;
|
||||
|
||||
/// <summary>
|
||||
/// An animator which visualizes whether the current perspective is the owner.
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user