Ready for PacMan??

This commit is contained in:
2026-01-13 21:28:53 +01:00
parent da0e6699e7
commit 65b153f97d
3 changed files with 605 additions and 347 deletions

View File

@@ -9700,7 +9700,6 @@ Transform:
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 963448677}
- {fileID: 1381489908}
m_Father: {fileID: 1886023632}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1001 &300095180
@@ -22129,6 +22128,7 @@ Transform:
- {fileID: 1334822256}
- {fileID: 1683006206}
- {fileID: 2841572}
- {fileID: 1381489908}
m_Father: {fileID: 1886023632}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!4 &712932630 stripped
@@ -25358,6 +25358,9 @@ MonoBehaviour:
- {fileID: 1910438138}
- {fileID: 1407423087}
- {fileID: 1541737191}
delay: 1
maxEventSendTries: 3
pingDelay: 0.3
DebugImageToIndicateOwner: {fileID: 0}
--- !u!1 &817541382 stripped
GameObject:
@@ -37775,6 +37778,9 @@ MonoBehaviour:
- {fileID: 1156754006}
- {fileID: 527776391}
- {fileID: 357748371}
delay: 1
maxEventSendTries: 3
pingDelay: 0.3
DebugImageToIndicateOwner: {fileID: 1745114900}
--- !u!1 &1203813879
GameObject:
@@ -42971,12 +42977,12 @@ Transform:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1381489907}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 4.266148, y: 14.909718, z: -30.038902}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 297676220}
m_Father: {fileID: 712073434}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1001 &1381602940
PrefabInstance:

File diff suppressed because it is too large Load Diff

View File

@@ -40,9 +40,28 @@ namespace Marro.PacManUdon
// [7]: (byte) Type of event. 0 = Full Sync, which is used to sync up from an undefinted state.
// [+]: Event-specific data.
#region Settings
/// <summary>
/// Objects which are controlled by this <see cref="NetworkManager"/>.
/// </summary>
[SerializeField] private SyncedObject[] syncedObjects;
/// <summary>
/// The delay at which the receiving side replays events.
/// </summary>
[SerializeField] private float delay = 1f;
/// <summary>
/// The maximum amount of times a message is sent.
/// </summary>
[SerializeField] private int maxEventSendTries = 3;
/// <summary>
/// How long to wait since last message to send next ping.
/// </summary>
[SerializeField] private float pingDelay = 0.3f;
#endregion
#region Constants
/// <summary>
/// The maximum size of the buffer in bytes.
/// The maximum amount of events in the buffer.
/// </summary>
private const int BufferMaxTotalEvents = 255;
@@ -66,23 +85,9 @@ namespace Marro.PacManUdon
/// The total length of the header of an event, in bytes.
/// </summary>
private const ushort HeaderLength = 8;
/// <summary>
/// The delay at which the receiving side replays events.
/// </summary>
private const float Delay = 1f;
/// <summary>
/// The maximum amount of times a message is sent
/// </summary>
private const int MaxEventSendTries = 3;
#endregion
#region Private attributes
/// <summary>
/// Objects which are controlled by this <see cref="NetworkManager"/>.
/// </summary>
[SerializeField] private SyncedObject[] syncedObjects;
/// <summary>
/// Offset from system time to network time, including delay.
/// </summary>
@@ -113,7 +118,7 @@ namespace Marro.PacManUdon
private bool serializationRequested;
/// <summary>
/// Queue of events to be transmitted or processed
/// Queue of events to be transmitted or processed.
/// </summary>
private byte[][] eventsQueue;
/// <summary>
@@ -122,23 +127,29 @@ namespace Marro.PacManUdon
private int eventsQueueIndex;
/// <summary>
/// The value of <see cref="eventsQueueIndex"/> at the last transmission
/// The value of <see cref="eventsQueueIndex"/> at the last transmission.
/// </summary>
private int eventsQueueIndexAtLastTransmission;
/// <summary>
/// Counts of new events at recent transmissions
/// Counts of new events at recent transmissions.
/// </summary>
private int[] eventTransmissionHistory;
/// <summary>
/// Index of <see cref="eventTransmissionHistoryIndex"/>
/// Index of <see cref="eventTransmissionHistoryIndex"/>.
/// </summary>
private int eventTransmissionHistoryIndex;
/// <summary>
/// Time of last event transmission.
/// </summary>
private float lastEventTransmissionTime;
/// <summary>
/// The message id of the most recent event created or received.
/// </summary>
private byte lastEventId;
/// <summary>
/// Data which is currently available on the network.
/// </summary>
@@ -218,10 +229,16 @@ namespace Marro.PacManUdon
// Fetch the current time
UpdateInternalTime();
// If able and needed, process received events
if (Ready && !IsOwner)
if (Ready)
{
ProgressEventTime();
if (IsOwner)
{
ProgressPingTime(); // See if we need to send a ping
}
else
{
ProgressEventTime(); // See if there's events that need to be replayed
}
}
// Forwards simulated time at the FixedUpdate pace
@@ -386,6 +403,15 @@ namespace Marro.PacManUdon
SendEvent(eventType);
}
private void ProgressPingTime()
{
if (eventsQueueIndex > 0
&& internalTime - lastEventTransmissionTime >= pingDelay)
{
RequestSerializationForEvents();
}
}
public override void OnPreSerialization()
{
if (!Ready || !IsOwner || !serializationRequested || eventsQueue == null || eventsQueueIndex == 0)
@@ -431,6 +457,8 @@ namespace Marro.PacManUdon
// If there was a full sync in the queue, it has now been transmitted at least once
hasFullSyncReady = false;
lastEventTransmissionTime = internalTime;
}
#endregion
@@ -492,16 +520,18 @@ namespace Marro.PacManUdon
var timestamp = GetTimestampFromHeader(@event);
var eventId = GetEventIdFromHeader(@event);
var eventType = GetEventTypeFromHeader(@event);
if (Synced || hasFullSyncReady)
if (eventType != NetworkEventType.FullSyncForced && (Synced || hasFullSyncReady))
{
// Check if event id is sequential
if (eventId != GetNextEventId(lastEventId))
{
if (index + eventSize >= length // If this is the last event of the batch
&& eventId != lastEventId) // Unless the eventId is the same, then this is probably just a duplicate
{
// The last event of the batch has to be synced up with our current event id count, else we've missed an event
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) EventIds were not sequential! Did we miss a serialization? Timestamp: {timestamp}, eventId: {eventId}, lastEventId: {lastEventId}.");
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) EventIds were not sequential! Did we miss an event? Timestamp: {timestamp}, eventId: {eventId}, lastEventId: {lastEventId}.");
HandleError(false);
return;
}
@@ -517,7 +547,7 @@ namespace Marro.PacManUdon
else
{
// If we're not yet synced, we only care about full sync events.
if (IsFullSync(GetEventTypeFromHeader(@event)))
if (IsFullSync(eventType))
{
QueueFullSyncForReplay(@event); // Immediately process full sync
}
@@ -539,7 +569,7 @@ namespace Marro.PacManUdon
QueueEventInBuffer(@event);
// Set this event to play after the default delay
nextEventTime = internalTime + Delay;
nextEventTime = internalTime + delay;
hasFullSyncReady = true;
@@ -634,7 +664,7 @@ namespace Marro.PacManUdon
{
eventsQueue = new byte[BufferMaxTotalEvents][];
eventsQueueIndex = 0;
eventTransmissionHistory = new int[MaxEventSendTries];
eventTransmissionHistory = new int[maxEventSendTries];
eventTransmissionHistoryIndex = 0;
eventsQueueIndexAtLastTransmission = 0;
lastEventId = 0;
@@ -702,16 +732,22 @@ namespace Marro.PacManUdon
}
var nextEventTime = GetTimestampFromHeader(eventsQueue[0]);
if (nextEventTime >= this.nextEventTime)
{
this.nextEventTime = nextEventTime;
}
else
if (nextEventTime < this.nextEventTime)
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) New event is earlier than previous event!");
HandleError(true);
return;
}
if (nextEventTime < SyncedTime)
{
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}");
HandleError(true);
return;
}
this.nextEventTime = nextEventTime;
}
#endregion
@@ -752,7 +788,13 @@ namespace Marro.PacManUdon
return;
}
SetOwner(newOwner == Networking.LocalPlayer);
bool newOwnerIsLocalPlayer = newOwner == Networking.LocalPlayer;
SetOwner(newOwnerIsLocalPlayer);
if (newOwnerIsLocalPlayer)
{
SendEvent(NetworkEventType.FullSyncForced);
}
}
#endregion