Implemented event subscribers

This commit is contained in:
2026-06-11 12:05:38 +02:00
parent e75452b145
commit f0859d92ac
10 changed files with 6684 additions and 62732 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -67,6 +67,9 @@ namespace Marro.PacManUdon
soundManager.Initialize();
intermission2Pole.Initialize(this, ghostManager.Ghosts[0]);
SubscribeToEvent(NetworkEventType.StartGameButtonPressed);
SubscribeToEvent(NetworkEventType.TimeSequenceSync);
HideEverything();
SetScore(0);

View File

@@ -109,6 +109,8 @@ namespace Marro.PacManUdon
frozenState = PacManGhostFrozenState.Frozen;
Index = index;
SubscribeToEvent(NetworkEventType.GhostUpdate);
}
public void Reset()

View File

@@ -74,6 +74,8 @@ namespace Marro.PacManUdon
ghosts[ghostIndex].Initialize(pacMan, blinky, startTransform, homePosition, idlePosition1, idlePosition2, cornerPosition, ghostIndex);
}
SubscribeToEvent(NetworkEventType.GhostUpdate);
}
public void RestartLevel(bool afterLifeLost = false)

File diff suppressed because it is too large Load Diff

View File

@@ -3,10 +3,8 @@ using System.Text;
using TMPro;
using UdonSharp;
using UnityEngine;
using UnityEngine.Android;
using VRC.SDK3.UdonNetworkCalling;
using VRC.SDKBase;
using VRC.SDKBase.Midi;
using VRC.Udon.Common;
namespace Marro.PacManUdon
@@ -48,11 +46,6 @@ 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 External settings
[SerializeField] private SyncedObject[] networkEventSubscribersFlat;
[SerializeField] private int[] networkEventSubscribersFlatSegmentLengths;
#endregion
#region Settings
/// <summary>
/// The root from which this <see cref="NetworkManager"/> will look for <see cref="SyncedObject"/> to control.
@@ -119,6 +112,11 @@ namespace Marro.PacManUdon
/// </summary>
private SyncedObject[][] networkEventSubscribers;
/// <summary>
/// Indices for <see cref="networkEventSubscribers"/>.
/// </summary>
private int[] networkEventSubscribersIndices;
/// <summary>
/// Subscribers for <see cref="SyncedObject.SyncedUpdate"/>.
/// </summary>
@@ -234,11 +232,11 @@ namespace Marro.PacManUdon
}
}
/// <summary>
/// Whether the current perspective is synced with the owner. (Always true if current perspective is owner.)
/// </summary>
public bool Synced
public bool Synced
{
get => synced;
private set
@@ -310,66 +308,28 @@ namespace Marro.PacManUdon
root = transform.parent.gameObject;
}
if (!TryGetNetworkEventSubscribers(out networkEventSubscribers))
{
Debug.LogError($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Fatal: Invalid NetworkEventSubscribers configuration! Network sync will not be possible.");
return;
}
syncedUpdateSubscribers = root.GetComponentsInChildren<SyncedObject>(includeInactive: true);
AssignNetworkManagerReferencesToSubscribers();
Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Found {syncedUpdateSubscribers.Length} {nameof(SyncedObject)} in children of {root.name}.");
InitializeSubscribers();
initialized = true;
Reset();
}
private bool TryGetNetworkEventSubscribers(out SyncedObject[][] result)
private void InitializeSubscribers()
{
result = new SyncedObject[0][];
return true;
var values = networkEventSubscribersFlat;
var lengths = networkEventSubscribersFlatSegmentLengths;
syncedUpdateSubscribers = root.GetComponentsInChildren<SyncedObject>(includeInactive: true);
result = new SyncedObject[lengths.Length][];
var index = 0;
foreach (var length in lengths)
{
if (index + length >= values.Length)
{
Debug.LogError($"({nameof(PacManUdon)} {nameof(NetworkManager)}) {nameof(TryGetNetworkEventSubscribers)}: Lengths sum is larger than values.");
return false;
}
result[index] = new SyncedObject[length];
Array.Copy(values, index, result, 0, length);
index += length;
}
if (index != values.Length)
{
Debug.LogError($"({nameof(PacManUdon)} {nameof(NetworkManager)}) {nameof(TryGetNetworkEventSubscribers)}: Lengths sum is smaller than values.");
}
return true;
}
private void AssignNetworkManagerReferencesToSubscribers()
{
// This results in a lot of duplicated assignments, but the alternative is deduplicating and unfortunately Udon does not have a good method for this.
foreach (var obj in syncedUpdateSubscribers)
{
obj.networkManager = this;
}
foreach (var obj in networkEventSubscribersFlat)
{
obj.networkManager = this;
}
Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Found {syncedUpdateSubscribers.Length} {nameof(SyncedObject)} in children of {root.name}.");
const int eventTypeCount = byte.MaxValue + 1;
networkEventSubscribers = new SyncedObject[eventTypeCount][];
networkEventSubscribersIndices = new int[eventTypeCount];
}
public void Reset()
@@ -401,6 +361,8 @@ namespace Marro.PacManUdon
SyncedDeltaTime = Time.fixedDeltaTime;
nextUpdateTime = SyncedTime;
Ready = true;
// Sync up
if (IsOwner)
{
@@ -411,8 +373,6 @@ namespace Marro.PacManUdon
RequestEvent(NetworkEventType.FullSync);
}
Ready = true;
Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Initialized, time offset: {offsetTime}");
}
@@ -516,9 +476,31 @@ namespace Marro.PacManUdon
}
}
private SyncedObject[] GetEventSubscribers(NetworkEventType eventType) =>
//networkEventSubscribers[(int)eventType];
syncedUpdateSubscribers;
private SyncedObject[] GetEventSubscribers(NetworkEventType eventType) => networkEventSubscribers[(int)eventType];
public void SubscribeToEvent(SyncedObject syncedObject, NetworkEventType eventType)
{
// This is inefficient, but I'd rather initialize slowly than perform bounds checks in often called code
var eventTypeIndex = (int)eventType;
var subscribers = networkEventSubscribers[eventTypeIndex];
int subscribersIndex = networkEventSubscribersIndices[eventTypeIndex];
if (subscribers == null)
{
subscribers = new SyncedObject[1];
}
else
{
subscribers = new SyncedObject[subscribersIndex+1];
Array.Copy(networkEventSubscribers[eventTypeIndex], subscribers, subscribersIndex);
}
subscribers[subscribersIndex] = syncedObject;
networkEventSubscribers[eventTypeIndex] = subscribers;
networkEventSubscribersIndices[eventTypeIndex] = subscribersIndex;
}
#endregion
#region Sender
@@ -576,9 +558,12 @@ namespace Marro.PacManUdon
var subscibers = GetEventSubscribers(eventType);
foreach (var obj in subscibers)
if (subscibers != null)
{
obj.CollectSyncedData(data, ref index, eventType);
foreach (var obj in subscibers)
{
obj.CollectSyncedData(data, ref index, eventType);
}
}
// Validate and fill in event size
@@ -862,22 +847,27 @@ namespace Marro.PacManUdon
ProgressSyncedTime(timestamp);
var subscibers = GetEventSubscribers(eventType);
var subscribers = GetEventSubscribers(eventType);
foreach (var obj in subscibers)
Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) ApplyEvent with dt {SyncedDeltaTime}");
if (subscribers != null)
{
obj.SyncedUpdate();
}
foreach (var obj in subscibers)
{
var success = obj.WriteSyncedData(@event, ref index, eventType);
if (!success)
foreach (var obj in subscribers)
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Malformed data reported by {obj.name} during event type {eventType}!");
HandleError(true);
return false;
obj.SyncedUpdate();
}
foreach (var obj in subscribers)
{
var success = obj.WriteSyncedData(@event, ref index, eventType);
if (!success)
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Malformed data reported by {obj.name} during event type {eventType}!");
HandleError(true);
return false;
}
}
}
@@ -997,7 +987,7 @@ namespace Marro.PacManUdon
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}");

View File

@@ -50,6 +50,8 @@ namespace Marro.PacManUdon
hideUntilUnfrozen = false;
startPosition = startTransform.localPosition;
startRotation = startTransform.localRotation;
SubscribeToEvent(NetworkEventType.PacManTurn);
}
public void Reset()

View File

@@ -28,6 +28,8 @@ namespace Marro.PacManUdon
SetPowerPelletsBlink(false);
RestoreAllPellets();
SubscribeToEvent(NetworkEventType.SyncPellets);
}
public override void SyncedUpdate()

View File

@@ -11,5 +11,7 @@ namespace Marro.PacManUdon
public virtual void SyncedUpdate() { }
public abstract void CollectSyncedData(byte[] data, ref int index, NetworkEventType eventType);
public abstract bool WriteSyncedData(byte[] data, ref int index, NetworkEventType eventType);
protected void SubscribeToEvent(NetworkEventType eventType) => networkManager.SubscribeToEvent(this, eventType);
}
}