Compare commits

...

3 Commits

Author SHA1 Message Date
06c26eb03e Working pretty well 2026-01-03 20:02:17 +01:00
a88e4bde81 Sync seems to work 2026-01-03 16:07:28 +01:00
68016b1d78 Working on networkmanager 2026-01-03 15:41:46 +01:00
16 changed files with 4563 additions and 2762 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -88,7 +88,7 @@ namespace Marro.PacManUdon
StartAttractMode(); StartAttractMode();
} }
public override void FixedUpdate() public override void SyncedUpdate()
{ {
TimeSequenceUpdate(Time.deltaTime); TimeSequenceUpdate(Time.deltaTime);
} }

File diff suppressed because it is too large Load Diff

View File

@@ -150,7 +150,7 @@ namespace Marro.PacManUdon
// Debug.Log($"{gameObject} reset with state: {state}, target: {target}, offGrid: {offGrid}"); // Debug.Log($"{gameObject} reset with state: {state}, target: {target}, offGrid: {offGrid}");
} }
public override void FixedUpdate() public override void SyncedUpdate()
{ {
if (ghostType == PacManGhostType.Blinky) if (ghostType == PacManGhostType.Blinky)
{ {

View File

@@ -43,7 +43,7 @@ MonoBehaviour:
Data: Data:
- Name: - Name:
Entry: 12 Entry: 12
Data: 11 Data: 15
- Name: - Name:
Entry: 7 Entry: 7
Data: Data:
@@ -115,19 +115,19 @@ MonoBehaviour:
Data: Data:
- Name: $k - Name: $k
Entry: 1 Entry: 1
Data: DebugImageToIndicateOwner Data: isOwner
- Name: $v - Name: $v
Entry: 7 Entry: 7
Data: 7|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor Data: 7|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField - Name: <Name>k__BackingField
Entry: 1 Entry: 1
Data: DebugImageToIndicateOwner Data: isOwner
- Name: <UserType>k__BackingField - Name: <UserType>k__BackingField
Entry: 7 Entry: 7
Data: 8|System.RuntimeType, mscorlib Data: 8|System.RuntimeType, mscorlib
- Name: - Name:
Entry: 1 Entry: 1
Data: UnityEngine.Animator, UnityEngine.AnimationModule Data: System.Boolean, mscorlib
- Name: - Name:
Entry: 8 Entry: 8
Data: Data:
@@ -145,70 +145,10 @@ MonoBehaviour:
Data: Data:
- Name: <IsSerialized>k__BackingField - Name: <IsSerialized>k__BackingField
Entry: 5 Entry: 5
Data: true Data: false
- Name: _fieldAttributes - Name: _fieldAttributes
Entry: 7 Entry: 7
Data: 9|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib Data: 9|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 1
- Name:
Entry: 7
Data: 10|UnityEngine.SerializeField, UnityEngine.CoreModule
- Name:
Entry: 8
Data:
- 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: isOwner
- Name: $v
Entry: 7
Data: 11|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: isOwner
- Name: <UserType>k__BackingField
Entry: 7
Data: 12|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: System.Boolean, mscorlib
- Name:
Entry: 8
Data:
- Name: <SystemType>k__BackingField
Entry: 9
Data: 12
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 13|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name: - Name:
Entry: 12 Entry: 12
Data: 0 Data: 0
@@ -232,16 +172,16 @@ MonoBehaviour:
Data: isSynced Data: isSynced
- Name: $v - Name: $v
Entry: 7 Entry: 7
Data: 14|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor Data: 10|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField - Name: <Name>k__BackingField
Entry: 1 Entry: 1
Data: isSynced Data: isSynced
- Name: <UserType>k__BackingField - Name: <UserType>k__BackingField
Entry: 9 Entry: 9
Data: 12 Data: 8
- Name: <SystemType>k__BackingField - Name: <SystemType>k__BackingField
Entry: 9 Entry: 9
Data: 12 Data: 8
- Name: <SyncMode>k__BackingField - Name: <SyncMode>k__BackingField
Entry: 7 Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
@@ -256,7 +196,7 @@ MonoBehaviour:
Data: false Data: false
- Name: _fieldAttributes - Name: _fieldAttributes
Entry: 7 Entry: 7
Data: 15|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib Data: 11|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name: - Name:
Entry: 12 Entry: 12
Data: 0 Data: 0
@@ -277,25 +217,121 @@ MonoBehaviour:
Data: Data:
- Name: $k - Name: $k
Entry: 1 Entry: 1
Data: startTimeTicks Data: offsetTime
- Name: $v - Name: $v
Entry: 7 Entry: 7
Data: 16|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor Data: 12|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField - Name: <Name>k__BackingField
Entry: 1 Entry: 1
Data: startTimeTicks Data: offsetTime
- Name: <UserType>k__BackingField - Name: <UserType>k__BackingField
Entry: 7 Entry: 7
Data: 17|System.RuntimeType, mscorlib Data: 13|System.RuntimeType, mscorlib
- Name: - Name:
Entry: 1 Entry: 1
Data: System.Int64, mscorlib Data: System.Single, mscorlib
- Name: - Name:
Entry: 8 Entry: 8
Data: Data:
- Name: <SystemType>k__BackingField - Name: <SystemType>k__BackingField
Entry: 9 Entry: 9
Data: 17 Data: 13
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 14|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: internalTime
- Name: $v
Entry: 7
Data: 15|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: internalTime
- Name: <UserType>k__BackingField
Entry: 9
Data: 13
- Name: <SystemType>k__BackingField
Entry: 9
Data: 13
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 16|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: nextEventTime
- Name: $v
Entry: 7
Data: 17|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: nextEventTime
- Name: <UserType>k__BackingField
Entry: 9
Data: 13
- Name: <SystemType>k__BackingField
Entry: 9
Data: 13
- Name: <SyncMode>k__BackingField - Name: <SyncMode>k__BackingField
Entry: 7 Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
@@ -331,64 +367,16 @@ MonoBehaviour:
Data: Data:
- Name: $k - Name: $k
Entry: 1 Entry: 1
Data: nextEventTimeTicks Data: retriesWithoutSuccess
- Name: $v - Name: $v
Entry: 7 Entry: 7
Data: 19|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor Data: 19|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: nextEventTimeTicks
- Name: <UserType>k__BackingField
Entry: 9
Data: 17
- Name: <SystemType>k__BackingField
Entry: 9
Data: 17
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 20|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: retriesWithoutSuccess
- Name: $v
Entry: 7
Data: 21|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField - Name: <Name>k__BackingField
Entry: 1 Entry: 1
Data: retriesWithoutSuccess Data: retriesWithoutSuccess
- Name: <UserType>k__BackingField - Name: <UserType>k__BackingField
Entry: 7 Entry: 7
Data: 22|System.RuntimeType, mscorlib Data: 20|System.RuntimeType, mscorlib
- Name: - Name:
Entry: 1 Entry: 1
Data: System.Int32, mscorlib Data: System.Int32, mscorlib
@@ -397,7 +385,7 @@ MonoBehaviour:
Data: Data:
- Name: <SystemType>k__BackingField - Name: <SystemType>k__BackingField
Entry: 9 Entry: 9
Data: 22 Data: 20
- Name: <SyncMode>k__BackingField - Name: <SyncMode>k__BackingField
Entry: 7 Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
@@ -412,7 +400,7 @@ MonoBehaviour:
Data: false Data: false
- Name: _fieldAttributes - Name: _fieldAttributes
Entry: 7 Entry: 7
Data: 23|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib Data: 21|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name: - Name:
Entry: 12 Entry: 12
Data: 0 Data: 0
@@ -436,13 +424,13 @@ MonoBehaviour:
Data: buffer Data: buffer
- Name: $v - Name: $v
Entry: 7 Entry: 7
Data: 24|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor Data: 22|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField - Name: <Name>k__BackingField
Entry: 1 Entry: 1
Data: buffer Data: buffer
- Name: <UserType>k__BackingField - Name: <UserType>k__BackingField
Entry: 7 Entry: 7
Data: 25|System.RuntimeType, mscorlib Data: 23|System.RuntimeType, mscorlib
- Name: - Name:
Entry: 1 Entry: 1
Data: System.Byte[], mscorlib Data: System.Byte[], mscorlib
@@ -451,7 +439,55 @@ MonoBehaviour:
Data: Data:
- Name: <SystemType>k__BackingField - Name: <SystemType>k__BackingField
Entry: 9 Entry: 9
Data: 25 Data: 23
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>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: bufferIndex
- Name: $v
Entry: 7
Data: 25|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: bufferIndex
- Name: <UserType>k__BackingField
Entry: 9
Data: 20
- Name: <SystemType>k__BackingField
Entry: 9
Data: 20
- Name: <SyncMode>k__BackingField - Name: <SyncMode>k__BackingField
Entry: 7 Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
@@ -487,19 +523,73 @@ MonoBehaviour:
Data: Data:
- Name: $k - Name: $k
Entry: 1 Entry: 1
Data: index Data: networkedData
- Name: $v - Name: $v
Entry: 7 Entry: 7
Data: 27|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor Data: 27|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField - Name: <Name>k__BackingField
Entry: 1 Entry: 1
Data: index Data: networkedData
- Name: <UserType>k__BackingField - Name: <UserType>k__BackingField
Entry: 9 Entry: 9
Data: 22 Data: 23
- Name: <SystemType>k__BackingField - Name: <SystemType>k__BackingField
Entry: 9 Entry: 9
Data: 22 Data: 23
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 3
Data: 1
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 28|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 1
- Name:
Entry: 7
Data: 29|UdonSharp.UdonSyncedAttribute, UdonSharp.Runtime
- Name:
Entry: 8
Data:
- 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: <Ready>k__BackingField
- Name: $v
Entry: 7
Data: 30|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: <Ready>k__BackingField
- Name: <UserType>k__BackingField
Entry: 9
Data: 8
- Name: <SystemType>k__BackingField
Entry: 9
Data: 8
- Name: <SyncMode>k__BackingField - Name: <SyncMode>k__BackingField
Entry: 7 Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
@@ -514,7 +604,7 @@ MonoBehaviour:
Data: false Data: false
- Name: _fieldAttributes - Name: _fieldAttributes
Entry: 7 Entry: 7
Data: 28|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib Data: 31|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name: - Name:
Entry: 12 Entry: 12
Data: 0 Data: 0
@@ -535,73 +625,19 @@ MonoBehaviour:
Data: Data:
- Name: $k - Name: $k
Entry: 1 Entry: 1
Data: networkedData Data: <SyncedTime>k__BackingField
- Name: $v
Entry: 7
Data: 29|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: networkedData
- Name: <UserType>k__BackingField
Entry: 9
Data: 25
- Name: <SystemType>k__BackingField
Entry: 9
Data: 25
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 3
Data: 1
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 30|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 1
- Name:
Entry: 7
Data: 31|UdonSharp.UdonSyncedAttribute, UdonSharp.Runtime
- Name:
Entry: 8
Data:
- 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: <CurrentTimeTicks>k__BackingField
- Name: $v - Name: $v
Entry: 7 Entry: 7
Data: 32|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor Data: 32|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField - Name: <Name>k__BackingField
Entry: 1 Entry: 1
Data: <CurrentTimeTicks>k__BackingField Data: <SyncedTime>k__BackingField
- Name: <UserType>k__BackingField - Name: <UserType>k__BackingField
Entry: 9 Entry: 9
Data: 17 Data: 13
- Name: <SystemType>k__BackingField - Name: <SystemType>k__BackingField
Entry: 9 Entry: 9
Data: 17 Data: 13
- Name: <SyncMode>k__BackingField - Name: <SyncMode>k__BackingField
Entry: 7 Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
@@ -632,6 +668,162 @@ MonoBehaviour:
- Name: - Name:
Entry: 8 Entry: 8
Data: Data:
- Name:
Entry: 7
Data:
- Name: $k
Entry: 1
Data: <Dt>k__BackingField
- Name: $v
Entry: 7
Data: 34|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: <Dt>k__BackingField
- Name: <UserType>k__BackingField
Entry: 9
Data: 13
- Name: <SystemType>k__BackingField
Entry: 9
Data: 13
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 35|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: <IsEventUpdate>k__BackingField
- Name: $v
Entry: 7
Data: 36|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: <IsEventUpdate>k__BackingField
- Name: <UserType>k__BackingField
Entry: 9
Data: 8
- Name: <SystemType>k__BackingField
Entry: 9
Data: 8
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 37|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: 38|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: DebugImageToIndicateOwner
- Name: <UserType>k__BackingField
Entry: 7
Data: 39|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: UnityEngine.Animator, UnityEngine.AnimationModule
- Name:
Entry: 8
Data:
- Name: <SystemType>k__BackingField
Entry: 9
Data: 39
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: true
- Name: _fieldAttributes
Entry: 7
Data: 40|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 1
- Name:
Entry: 7
Data: 41|UnityEngine.SerializeField, UnityEngine.CoreModule
- Name:
Entry: 8
Data:
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name: - Name:
Entry: 13 Entry: 13
Data: Data:

View File

@@ -3,8 +3,10 @@ using JetBrains.Annotations;
using System; using System;
using System.Drawing; using System.Drawing;
using System.Text; using System.Text;
using TMPro;
using UdonSharp; using UdonSharp;
using UnityEngine; using UnityEngine;
using UnityEngine.UI;
using VRC.SDK3.UdonNetworkCalling; using VRC.SDK3.UdonNetworkCalling;
using VRC.SDKBase; using VRC.SDKBase;
using VRC.Udon.ClientBindings.Interfaces; using VRC.Udon.ClientBindings.Interfaces;
@@ -37,35 +39,132 @@ namespace Marro.PacManUdon
// [6]: (byte) Type of event. 0 = Full Sync, which is used to sync up from an undefinted state. // [6]: (byte) Type of event. 0 = Full Sync, which is used to sync up from an undefinted state.
// [7+]: Event-specific data // [7+]: Event-specific data
#region Constants
/// <summary>
/// The maximum size of the buffer in bytes.
/// </summary>
private const int BufferMaxSizeBytes = 10000; private const int BufferMaxSizeBytes = 10000;
/// <summary>
/// How many bytes to increase the buffer size by if the current one is not enough.
/// </summary>
private const int BufferIncrementSizeBytes = 1000; private const int BufferIncrementSizeBytes = 1000;
[SerializeField] private SyncedObject[] syncedObjects; /// <summary>
/// The index in an event where the event size is stored.
[SerializeField] private Animator DebugImageToIndicateOwner; /// </summary>
private bool isOwner;
private bool isSynced;
private long startTimeTicks = DateTime.UtcNow.Ticks; // Initialize to prevent errors
private long nextEventTimeTicks;
private int retriesWithoutSuccess;
// Main buffer of events
private byte[] buffer;
private int index;
private const ushort HeaderEventSizeIndex = 0; private const ushort HeaderEventSizeIndex = 0;
/// <summary>
/// The index in an event where the timestamp is stored.
/// </summary>
private const ushort HeaderTimestampIndex = 2; private const ushort HeaderTimestampIndex = 2;
/// <summary>
/// The index in an event where the event type is stored.
/// </summary>
private const ushort HeaderEventTypeIndex = 6; private const ushort HeaderEventTypeIndex = 6;
/// <summary>
/// The total length of the header of an event, in bytes.
/// </summary>
private const ushort HeaderLength = 7; private const ushort HeaderLength = 7;
private const int Delay = 250; /// <summary>
/// The multiplier from Unity time to a timestamp.
/// </summary>
private const int TimestampMultiplier = 1000;
/// <summary>
/// The zero value of a timestamp. Anything below this value is negative.
/// </summary>
private const uint TimestampZeroValue = 1000;
/// <summary>
/// The delay at which the receiving side replays events.
/// </summary>
private const float Delay = 1f;
#endregion
#region Private attributes
/// <summary>
/// Objects which are controlled by this <see cref="NetworkManager"/>.
/// </summary>
[SerializeField] private SyncedObject[] syncedObjects;
/// <summary>
/// Whether the current perspective is the transmitting side.
/// </summary>
private bool isOwner;
/// <summary>
/// Whether the current perspective is synced with the owner. (Always true if current perspective is owner.)
/// </summary>
private bool isSynced;
/// <summary>
/// Offset from system time to network time, including delay.
/// </summary>
private float offsetTime;
/// <summary>
/// Time since last full sync, captured when this FixedUpdate started, with network delay applied.
/// </summary>
private float internalTime;
/// <summary>
/// Time at which next received event occured.
/// </summary>
private float nextEventTime;
/// <summary>
/// Amounot of retries in a row without a successful sync.
/// </summary>
private int retriesWithoutSuccess;
/// <summary>
/// Main buffer of data to be transmitted or processed
/// </summary>
private byte[] buffer;
/// <summary>
/// Index of <see cref="buffer"/>.
/// </summary>
private int bufferIndex;
/// <summary>
/// Data which is currently available on the network.
/// </summary>
[UdonSynced] private byte[] networkedData = new byte[0]; [UdonSynced] private byte[] networkedData = new byte[0];
#endregion
public long CurrentTimeTicks { get; private set; } #region Public fields
/// <summary>
/// Whether this <see cref="NetworkManager"/> is ready to transmit or receive data.
/// If false, networking is disabled and this <see cref="NetworkManager"/> acts as a pass-through.
/// </summary>
public bool Ready { get; private set; } = false;
/// <summary>
/// The time since last full sync which is currently being simulated.
/// </summary>
public float SyncedTime { get; private set; }
/// <summary>
/// Time since the last simulation, in seconds.
/// </summary>
public float Dt { get; private set; }
/// <summary>
/// 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
/// </summary>
public bool IsEventUpdate { get; private set; }
/// <summary>
/// Is the local user owner?
/// </summary>
public bool IsOwner => isOwner;
#endregion
#region General
public void Awake()
{
offsetTime = Time.fixedTime;
}
public void Initialize() public void Initialize()
{ {
@@ -77,328 +176,49 @@ namespace Marro.PacManUdon
return; return;
} }
buffer = new byte[BufferIncrementSizeBytes];
index = 0;
startTimeTicks = DateTime.UtcNow.Ticks;
isSynced = false;
retriesWithoutSuccess = 0;
SetOwner(Networking.IsOwner(gameObject)); SetOwner(Networking.IsOwner(gameObject));
Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Initialized, startTimeTicks: {startTimeTicks}"); buffer = new byte[BufferIncrementSizeBytes];
bufferIndex = 0;
isSynced = isOwner; // Owner is always synced
retriesWithoutSuccess = 0;
offsetTime = Time.fixedTime;
internalTime = 0;
SyncedTime = 0;
Dt = Time.fixedDeltaTime;
Ready = true;
Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Initialized, time offset: {offsetTime}");
} }
public void Update() public void FixedUpdate()
{ {
UpdateInternalTime();
if (!isOwner) if (!isOwner)
{ {
ProgressReplayTime(); ProgressEventTime();
} }
UpdateTime(DateTime.UtcNow.Ticks); PerformFixedSyncedUpdate();
} }
public void SendEvent(NetworkEventType eventType) public void UpdateInternalTime()
{ {
if (!isOwner) internalTime = Time.fixedTime - offsetTime;
{ }
Debug.LogError($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Attempted {nameof(SendEvent)} while not the owner!");
return;
}
var eventTime = GetTimestamp(CurrentTimeTicks); private void PerformFixedSyncedUpdate()
{
InitializeEvent(eventType, eventTime, BufferMaxSizeBytes, out byte[][] data, out var index); IsEventUpdate = false;
ProgressSyncedTime(internalTime);
foreach (var obj in syncedObjects) foreach (var obj in syncedObjects)
{ {
obj.AppendSyncedData(data, ref index, eventType); obj.SyncedUpdate();
} }
// Get event size, skipping over the event size which is not yet included
ushort eventSize = 0;
for (int i = 0; i < index; i++)
{
eventSize += (ushort)data[i].Length;
}
if (!EnsureSpaceToStoreEvent(eventSize))
{
return;
}
data[0] = BitConverter.GetBytes(eventSize);
var oldIndex = this.index;
FlattenAndCopy(data, index, buffer, ref this.index);
Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Prepared event with {eventSize} bytes and timestamp {eventTime} for serialization, index went from {oldIndex} to {this.index}");
RequestSerialization();
retriesWithoutSuccess = 0; // We had success!
}
public void RequestEvent(NetworkEventType eventType)
{
if (isOwner)
{
Debug.LogError($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Attempted {nameof(RequestEvent)} while we are the owner!");
return;
}
SendCustomNetworkEvent(VRC.Udon.Common.Interfaces.NetworkEventTarget.Owner, "RequestEventReceived", eventType);
}
[NetworkCallable]
public void RequestEventReceived(NetworkEventType eventType)
{
if (!isOwner)
{
Debug.LogError($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Attempted {nameof(RequestEventReceived)} while we are not the owner!");
return;
}
SendEvent(eventType);
}
private void ProcessIncomingData()
{
if (networkedData.Length == 0)
{
return; // Nothing to process
}
var length = networkedData.Length;
int index = 0;
while (index < length)
{
if (length - index < HeaderLength)
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) {nameof(ProcessIncomingData)}: Remaining data in networkedData is not long enough to form a complete event!");
HandleError();
return;
}
var eventSize = networkedData[index + HeaderEventSizeIndex];
var eventType = (NetworkEventType)networkedData[index + HeaderEventTypeIndex];
if (eventType == NetworkEventType.FullSync)
{
ProcessIncomingFullSync(index, eventSize); // Immediately process full sync
index += eventSize;
continue;
}
if (!isSynced)
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Received event of type {eventType} while we are not yet synced to the remote time, ignoring event.");
index += eventSize;
continue;
}
AppendEventToBuffer(index, eventSize);
index += eventSize;
}
Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Received {networkedData.Length} bytes!\nBytes received:\n{BytesToString(networkedData)}");
}
private void ProcessIncomingFullSync(int index, int size)
{
// Intentionally not doing a buffer size check here, since this is not appending to the buffer
// (and there is no good way to continue if event is too large)
// Clear buffer and copy the full sync into it
buffer = new byte[size];
Array.Copy(networkedData, index, buffer, 0, size);
this.index = size;
// Sync up to the time in the full sync
var timestamp = BitConverter.ToUInt32(networkedData, index + HeaderTimestampIndex);
SyncToTimestamp(timestamp);
// Immediately apply the full sync
nextEventTimeTicks = GetTimeTicks(timestamp);
isSynced = true;
}
private void AppendEventToBuffer(int index, int size)
{
if (!EnsureSpaceToStoreEvent(size))
{
return;
}
Array.Copy(networkedData, index, buffer, this.index, size);
this.index += size;
UpdateNextEventTime();
}
private void ProgressReplayTime()
{
while (index != 0 && nextEventTimeTicks <= CurrentTimeTicks)
{
ProcessIncomingEvent();
UpdateNextEventTime();
}
}
private void UpdateNextEventTime()
{
if (index == 0)
{
return;
}
var nextEventTimeTicks = GetTimeTicks(BitConverter.ToUInt32(buffer, HeaderTimestampIndex));
if (nextEventTimeTicks >= this.nextEventTimeTicks)
{
this.nextEventTimeTicks = nextEventTimeTicks;
}
else
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) New event is earlier than previous event!");
HandleError();
return;
}
}
private void ProcessIncomingEvent()
{
var eventTimeTicks = GetTimeTicks(BitConverter.ToUInt32(buffer, HeaderTimestampIndex));
var eventType = (NetworkEventType)buffer[HeaderEventTypeIndex];
var index = (int)HeaderLength; // Skip header
UpdateTime(eventTimeTicks);
foreach (var obj in syncedObjects)
{
obj.FixedUpdate();
}
foreach (var obj in syncedObjects)
{
var success = obj.SetSyncedData(buffer, ref index, eventType);
if (!success)
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Malformed data reported by {obj.name} during event type {eventType}!");
HandleError();
return;
}
if (index > this.index)
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Buffer overflow during {nameof(SyncedObject.SetSyncedData)} for {obj.name} in event type {eventType}!");
HandleError();
return;
}
}
var eventSize = BitConverter.ToUInt16(buffer, HeaderEventSizeIndex);
if (index != eventSize)
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Amount of data read does not match event size! Expected {eventSize}, read {index}.");
HandleError();
return;
}
RemoveProcessedDataFromBuffer(index);
Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Processed incoming event! Total {index} bytes.");
retriesWithoutSuccess = 0; // We had success!
}
private void SyncToTimestamp(uint newTime)
{
var timeToSyncTo = newTime - Delay;
startTimeTicks = DateTime.UtcNow.Ticks - timeToSyncTo * TimeSpan.TicksPerMillisecond;
Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Synced to time {newTime}, startTimeTicks is now {startTimeTicks}");
}
private bool EnsureSpaceToStoreEvent(int eventSize)
{
if (index + eventSize <= buffer.Length)
{
return true; // Enough space!
}
var newBufferSize = ((index + eventSize) / BufferIncrementSizeBytes + 1) * BufferIncrementSizeBytes;
var success = IncreaseBufferSize(newBufferSize);
if (success)
{
return true;
}
if (index == 0)
{
Debug.LogError($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Buffer is not large enough to store event!");
}
else
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Too much data in buffer to store event!");
}
HandleError(); // We can store event now that we cleared the buffer.
return false;
}
private bool IncreaseBufferSize(int newSize)
{
if (newSize < buffer.Length)
{
Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Cannot decrease the size of the buffer!");
return false;
}
if (newSize > BufferMaxSizeBytes)
{
return false;
}
var oldBuffer = buffer;
buffer = new byte[newSize];
oldBuffer.CopyTo(buffer, 0);
return true;
}
private void InitializeEvent(NetworkEventType eventType, uint eventTime, int maxSize, out byte[][] data, out int index)
{
data = new byte[maxSize][];
index = 3;
data[0] = new byte[2]; // Placeholder for event size
data[1] = BitConverter.GetBytes(eventTime);
data[2] = new byte[] { GameManager.Int32ToByte((int)eventType) };
}
private void FlattenAndCopy(byte[][] data, int length, byte[] target, ref int index)
{
for (int i = 0; i < length; i++)
{
var values = data[i];
Array.Copy(values, 0, target, index, values.Length);
index += values.Length;
}
}
private void RemoveProcessedDataFromBuffer(int amountProcessed)
{
var oldBuffer = buffer;
index -= amountProcessed;
buffer = new byte[BufferMaxSizeBytes];
Array.Copy(oldBuffer, amountProcessed, buffer, 0, index);
}
private void ClearBuffer()
{
buffer = new byte[BufferMaxSizeBytes];
index = 0;
} }
private void HandleError() private void HandleError()
@@ -436,7 +256,323 @@ namespace Marro.PacManUdon
DebugImageToIndicateOwner.SetFloat("Color", isOwner ? 1 : 0); DebugImageToIndicateOwner.SetFloat("Color", isOwner ? 1 : 0);
} }
} }
#endregion
#region Sender
public void SendEvent(NetworkEventType eventType)
{
if (!isOwner)
{
Debug.LogError($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Attempted {nameof(SendEvent)} while not the owner!");
return;
}
var eventTime = TimeToTimestamp(SyncedTime);
InitializeEvent(eventType, eventTime, BufferMaxSizeBytes, out byte[][] data, out var index);
foreach (var obj in syncedObjects)
{
obj.AppendSyncedData(data, ref index, eventType);
}
// Get event size, skipping over the event size which is not yet included
ushort eventSize = 0;
for (int i = 0; i < index; i++)
{
eventSize += (ushort)data[i].Length;
}
if (!EnsureSpaceToStoreEvent(eventSize))
{
return;
}
data[0] = BitConverter.GetBytes(eventSize);
var oldIndex = this.bufferIndex;
FlattenAndCopy(data, index, buffer, ref this.bufferIndex);
Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Prepared event with {eventSize} bytes and timestamp {eventTime} for serialization, index went from {oldIndex} to {this.bufferIndex}");
RequestSerialization();
retriesWithoutSuccess = 0; // We had success!
}
private static void InitializeEvent(NetworkEventType eventType, uint eventTime, int maxSize, out byte[][] data, out int index)
{
data = new byte[maxSize][];
index = 3;
data[0] = new byte[2]; // Placeholder for event size
data[1] = BitConverter.GetBytes(eventTime);
data[2] = new byte[] { GameManager.Int32ToByte((int)eventType) };
}
#endregion
#region Receiver
public void RequestEvent(NetworkEventType eventType)
{
if (isOwner)
{
Debug.LogError($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Attempted {nameof(RequestEvent)} while we are the owner!");
return;
}
SendCustomNetworkEvent(VRC.Udon.Common.Interfaces.NetworkEventTarget.Owner, "RequestEventReceived", eventType);
}
private void ProcessIncomingData()
{
if (networkedData.Length == 0)
{
return; // Nothing to process
}
Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Received {networkedData.Length} bytes!\nBytes received:\n{BytesToString(networkedData)}");
var length = networkedData.Length;
int index = 0;
while (index < length)
{
if (length - index < HeaderLength)
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) {nameof(ProcessIncomingData)}: Remaining data in networkedData is not long enough to form a complete event!");
HandleError();
return;
}
var eventSize = networkedData[index + HeaderEventSizeIndex];
var eventType = (NetworkEventType)networkedData[index + HeaderEventTypeIndex];
if (eventType == NetworkEventType.FullSync)
{
ProcessIncomingFullSync(index, eventSize); // Immediately process full sync
index += eventSize;
continue;
}
if (!isSynced)
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Received event of type {eventType} while we are not yet synced to the remote time, ignoring event.");
index += eventSize;
continue;
}
AppendEventToBuffer(index, eventSize);
index += eventSize;
}
}
private void ProcessIncomingFullSync(int index, int size)
{
// 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 copy the full sync into it
buffer = new byte[size];
Array.Copy(networkedData, index, buffer, 0, size);
this.bufferIndex = size;
// Sync up to the time in the full sync
var timestamp = BitConverter.ToUInt32(networkedData, index + HeaderTimestampIndex);
SyncToTimestamp(timestamp);
// Immediately apply the full sync
UpdateNextEventTime(ignoreOrder: true);
isSynced = true;
}
private void ProgressEventTime()
{
IsEventUpdate = true;
while (bufferIndex != 0 && nextEventTime <= internalTime)
{
ProcessIncomingEvent();
UpdateNextEventTime();
}
}
private void ProcessIncomingEvent()
{
var eventTime = TimestampToTime(BitConverter.ToUInt32(buffer, HeaderTimestampIndex));
var eventType = (NetworkEventType)buffer[HeaderEventTypeIndex];
var index = (int)HeaderLength; // Skip header
ProgressSyncedTime(eventTime);
foreach (var obj in syncedObjects)
{
obj.SyncedUpdate();
}
foreach (var obj in syncedObjects)
{
var success = obj.SetSyncedData(buffer, ref index, eventType);
if (!success)
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Malformed data reported by {obj.name} during event type {eventType}!");
HandleError();
return;
}
if (index > this.bufferIndex)
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Buffer overflow during {nameof(SyncedObject.SetSyncedData)} for {obj.name} in event type {eventType}!");
HandleError();
return;
}
}
var eventSize = BitConverter.ToUInt16(buffer, HeaderEventSizeIndex);
if (index != eventSize)
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Amount of data read does not match event size! Expected {eventSize}, read {index}.");
HandleError();
return;
}
RemoveProcessedDataFromBuffer(index);
Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Processed incoming event! Total {index} bytes.");
retriesWithoutSuccess = 0; // We had success!
}
#endregion
#region Buffer
private void ClearBuffer()
{
buffer = new byte[BufferMaxSizeBytes];
bufferIndex = 0;
}
private void RemoveProcessedDataFromBuffer(int amountProcessed)
{
var oldBuffer = buffer;
bufferIndex -= amountProcessed;
buffer = new byte[BufferMaxSizeBytes];
Array.Copy(oldBuffer, amountProcessed, buffer, 0, bufferIndex);
}
private bool IncreaseBufferSize(int newSize)
{
if (newSize < buffer.Length)
{
Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Cannot decrease the size of the buffer!");
return false;
}
if (newSize > BufferMaxSizeBytes)
{
return false;
}
var oldBuffer = buffer;
buffer = new byte[newSize];
oldBuffer.CopyTo(buffer, 0);
return true;
}
private bool EnsureSpaceToStoreEvent(int eventSize)
{
if (bufferIndex + eventSize <= buffer.Length)
{
return true; // Enough space!
}
var newBufferSize = ((bufferIndex + eventSize) / BufferIncrementSizeBytes + 1) * BufferIncrementSizeBytes;
var success = IncreaseBufferSize(newBufferSize);
if (success)
{
return true;
}
if (bufferIndex == 0)
{
Debug.LogError($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Buffer is not large enough to store event!");
}
else
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Too much data in buffer to store event!");
}
HandleError(); // We can store event now that we cleared the buffer.
return false;
}
private void AppendEventToBuffer(int index, int size)
{
if (!EnsureSpaceToStoreEvent(size))
{
return;
}
Array.Copy(networkedData, index, buffer, this.bufferIndex, size);
this.bufferIndex += size;
UpdateNextEventTime();
}
#endregion
#region Time
private void ProgressSyncedTime(float newTime)
{
//Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) updating SyncedTime from {SyncedTime} to {newTime}");
Dt = newTime - SyncedTime;
SyncedTime = newTime;
}
private void SyncToTimestamp(uint timestamp)
{
var oldOffset = offsetTime;
var timeToSyncTo = timestamp / (float)TimestampMultiplier - Delay;
offsetTime = Time.fixedTime - timeToSyncTo;
var delta = offsetTime - oldOffset;
internalTime = internalTime - delta;
SyncedTime = SyncedTime - delta;
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}");
}
private void UpdateNextEventTime(bool ignoreOrder = false)
{
if (bufferIndex == 0)
{
return;
}
var nextEventTime = TimestampToTime(BitConverter.ToUInt32(buffer, HeaderTimestampIndex));
if (ignoreOrder || nextEventTime >= this.nextEventTime)
{
this.nextEventTime = nextEventTime;
}
else
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) New event is earlier than previous event!");
HandleError();
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 VRC events
public override void OnOwnershipTransferred(VRCPlayerApi newOwner) public override void OnOwnershipTransferred(VRCPlayerApi newOwner)
{ {
SetOwner(newOwner == Networking.LocalPlayer); SetOwner(newOwner == Networking.LocalPlayer);
@@ -451,8 +587,8 @@ namespace Marro.PacManUdon
{ {
if (isOwner) if (isOwner)
{ {
networkedData = new byte[index]; networkedData = new byte[bufferIndex];
Array.Copy(buffer, networkedData, index); Array.Copy(buffer, networkedData, bufferIndex);
} }
else else
{ {
@@ -487,30 +623,9 @@ namespace Marro.PacManUdon
ProcessIncomingData(); ProcessIncomingData();
} }
} }
#endregion
private void UpdateTime(long timeTicks) #region Utils
{
CurrentTimeTicks = timeTicks;
foreach (var obj in syncedObjects)
{
obj.Dt = (timeTicks - obj.LastUpdateTicks) / (float)TimeSpan.TicksPerSecond;
obj.LastUpdateTicks = timeTicks;
}
}
public uint GetTimestamp(long timeTicks)
{
return (uint)((timeTicks - startTimeTicks) / TimeSpan.TicksPerMillisecond);
}
public long GetTimeTicks(uint timeStamp)
{
return timeStamp * TimeSpan.TicksPerMillisecond + startTimeTicks;
}
public bool IsOwner => isOwner;
public string BytesToString(byte[] bytes) public string BytesToString(byte[] bytes)
{ {
var sb = new StringBuilder("new byte[] { "); var sb = new StringBuilder("new byte[] { ");
@@ -521,5 +636,40 @@ namespace Marro.PacManUdon
sb.Append("}"); sb.Append("}");
return sb.ToString(); return sb.ToString();
} }
private static void FlattenAndCopy(byte[][] data, int length, byte[] target, ref int index)
{
for (int i = 0; i < length; i++)
{
var values = data[i];
Array.Copy(values, 0, target, index, values.Length);
index += values.Length;
}
}
#endregion
#region Debug
public void SimulateSyncToTimestamp(uint timestamp)
{
SyncToTimestamp(timestamp);
}
public void WriteDebugOutput(TMP_InputField debugOutput)
{
debugOutput.text += $"{nameof(NetworkManager)}:\n" +
$"IsOwner: {isOwner}\n" +
$"Time.fixedTime: {Time.fixedTime}\n" +
$"offsetTime: {offsetTime}\n" +
$"internalTime: {internalTime}\n" +
$"SyncedTime: {SyncedTime}\n" +
$"Dt: {Dt}\n" +
$"\n";
}
/// <summary>
/// An animator which visualizes whether the current perspective is the owner.
/// </summary>
[SerializeField] private Animator DebugImageToIndicateOwner;
#endregion
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -75,7 +75,7 @@
animator.SetTrigger("Reset"); animator.SetTrigger("Reset");
} }
public override void FixedUpdate() public override void SyncedUpdate()
{ {
// gameStateManager.statusDisplay.SetDebugText(1, this.targetDirection.ToString()); // gameStateManager.statusDisplay.SetDebugText(1, this.targetDirection.ToString());

View File

@@ -6,9 +6,7 @@ namespace Marro.PacManUdon
{ {
public abstract class SyncedObject : UdonSharpBehaviour public abstract class SyncedObject : UdonSharpBehaviour
{ {
public long LastUpdateTicks { get; set; } public abstract void SyncedUpdate();
public float Dt { get; set; }
public abstract void FixedUpdate();
public abstract void AppendSyncedData(byte[][] data, ref int index, NetworkEventType eventType); public abstract void AppendSyncedData(byte[][] data, ref int index, NetworkEventType eventType);
public abstract bool SetSyncedData(byte[] data, ref int index, NetworkEventType eventType); public abstract bool SetSyncedData(byte[] data, ref int index, NetworkEventType eventType);
} }

View File

@@ -43,25 +43,25 @@ MonoBehaviour:
Data: Data:
- Name: - Name:
Entry: 12 Entry: 12
Data: 7 Data: 9
- Name: - Name:
Entry: 7 Entry: 7
Data: Data:
- Name: $k - Name: $k
Entry: 1 Entry: 1
Data: <LastUpdateTicks>k__BackingField Data: start
- Name: $v - Name: $v
Entry: 7 Entry: 7
Data: 2|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor Data: 2|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField - Name: <Name>k__BackingField
Entry: 1 Entry: 1
Data: <LastUpdateTicks>k__BackingField Data: start
- Name: <UserType>k__BackingField - Name: <UserType>k__BackingField
Entry: 7 Entry: 7
Data: 3|System.RuntimeType, mscorlib Data: 3|System.RuntimeType, mscorlib
- Name: - Name:
Entry: 1 Entry: 1
Data: System.Int64, mscorlib Data: UnityEngine.Transform, UnityEngine.CoreModule
- Name: - Name:
Entry: 8 Entry: 8
Data: Data:
@@ -79,13 +79,19 @@ MonoBehaviour:
Data: Data:
- Name: <IsSerialized>k__BackingField - Name: <IsSerialized>k__BackingField
Entry: 5 Entry: 5
Data: false Data: true
- Name: _fieldAttributes - Name: _fieldAttributes
Entry: 7 Entry: 7
Data: 4|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib Data: 4|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name: - Name:
Entry: 12 Entry: 12
Data: 0 Data: 1
- Name:
Entry: 7
Data: 5|UnityEngine.SerializeField, UnityEngine.CoreModule
- Name:
Entry: 8
Data:
- Name: - Name:
Entry: 13 Entry: 13
Data: Data:
@@ -103,25 +109,19 @@ MonoBehaviour:
Data: Data:
- Name: $k - Name: $k
Entry: 1 Entry: 1
Data: <Dt>k__BackingField Data: end
- Name: $v - Name: $v
Entry: 7 Entry: 7
Data: 5|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor Data: 6|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField - Name: <Name>k__BackingField
Entry: 1 Entry: 1
Data: <Dt>k__BackingField Data: end
- Name: <UserType>k__BackingField - Name: <UserType>k__BackingField
Entry: 7 Entry: 9
Data: 6|System.RuntimeType, mscorlib Data: 3
- Name:
Entry: 1
Data: System.Single, mscorlib
- Name:
Entry: 8
Data:
- Name: <SystemType>k__BackingField - Name: <SystemType>k__BackingField
Entry: 9 Entry: 9
Data: 6 Data: 3
- Name: <SyncMode>k__BackingField - Name: <SyncMode>k__BackingField
Entry: 7 Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
@@ -133,13 +133,85 @@ MonoBehaviour:
Data: Data:
- Name: <IsSerialized>k__BackingField - Name: <IsSerialized>k__BackingField
Entry: 5 Entry: 5
Data: false Data: true
- Name: _fieldAttributes - Name: _fieldAttributes
Entry: 7 Entry: 7
Data: 7|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib Data: 7|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name: - Name:
Entry: 12 Entry: 12
Data: 0 Data: 1
- Name:
Entry: 7
Data: 8|UnityEngine.SerializeField, UnityEngine.CoreModule
- Name:
Entry: 8
Data:
- 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: mode
- Name: $v
Entry: 7
Data: 9|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: mode
- Name: <UserType>k__BackingField
Entry: 7
Data: 10|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: TestBallMode, Assembly-CSharp
- Name:
Entry: 8
Data:
- Name: <SystemType>k__BackingField
Entry: 7
Data: 11|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: System.Int32, mscorlib
- Name:
Entry: 8
Data:
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: true
- Name: _fieldAttributes
Entry: 7
Data: 12|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 1
- Name:
Entry: 7
Data: 13|UnityEngine.SerializeField, UnityEngine.CoreModule
- Name:
Entry: 8
Data:
- Name: - Name:
Entry: 13 Entry: 13
Data: Data:
@@ -160,13 +232,13 @@ MonoBehaviour:
Data: networkManager Data: networkManager
- Name: $v - Name: $v
Entry: 7 Entry: 7
Data: 8|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor Data: 14|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField - Name: <Name>k__BackingField
Entry: 1 Entry: 1
Data: networkManager Data: networkManager
- Name: <UserType>k__BackingField - Name: <UserType>k__BackingField
Entry: 7 Entry: 7
Data: 9|System.RuntimeType, mscorlib Data: 15|System.RuntimeType, mscorlib
- Name: - Name:
Entry: 1 Entry: 1
Data: Marro.PacManUdon.NetworkManager, Assembly-CSharp Data: Marro.PacManUdon.NetworkManager, Assembly-CSharp
@@ -175,7 +247,7 @@ MonoBehaviour:
Data: Data:
- Name: <SystemType>k__BackingField - Name: <SystemType>k__BackingField
Entry: 7 Entry: 7
Data: 10|System.RuntimeType, mscorlib Data: 16|System.RuntimeType, mscorlib
- Name: - Name:
Entry: 1 Entry: 1
Data: VRC.Udon.UdonBehaviour, VRC.Udon Data: VRC.Udon.UdonBehaviour, VRC.Udon
@@ -193,19 +265,13 @@ MonoBehaviour:
Data: Data:
- Name: <IsSerialized>k__BackingField - Name: <IsSerialized>k__BackingField
Entry: 5 Entry: 5
Data: true Data: false
- Name: _fieldAttributes - Name: _fieldAttributes
Entry: 7 Entry: 7
Data: 11|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib Data: 17|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name: - Name:
Entry: 12 Entry: 12
Data: 1 Data: 0
- Name:
Entry: 7
Data: 12|UnityEngine.SerializeField, UnityEngine.CoreModule
- Name:
Entry: 8
Data:
- Name: - Name:
Entry: 13 Entry: 13
Data: Data:
@@ -223,133 +289,25 @@ MonoBehaviour:
Data: Data:
- Name: $k - Name: $k
Entry: 1 Entry: 1
Data: start Data: sumOfDt
- Name: $v - Name: $v
Entry: 7 Entry: 7
Data: 13|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor Data: 18|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField - Name: <Name>k__BackingField
Entry: 1 Entry: 1
Data: start Data: sumOfDt
- Name: <UserType>k__BackingField - Name: <UserType>k__BackingField
Entry: 7 Entry: 7
Data: 14|System.RuntimeType, mscorlib Data: 19|System.RuntimeType, mscorlib
- Name: - Name:
Entry: 1 Entry: 1
Data: UnityEngine.Transform, UnityEngine.CoreModule Data: System.Single, mscorlib
- Name: - Name:
Entry: 8 Entry: 8
Data: Data:
- Name: <SystemType>k__BackingField - Name: <SystemType>k__BackingField
Entry: 9 Entry: 9
Data: 14 Data: 19
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: true
- Name: _fieldAttributes
Entry: 7
Data: 15|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 1
- Name:
Entry: 7
Data: 16|UnityEngine.SerializeField, UnityEngine.CoreModule
- Name:
Entry: 8
Data:
- 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: end
- Name: $v
Entry: 7
Data: 17|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: end
- Name: <UserType>k__BackingField
Entry: 9
Data: 14
- Name: <SystemType>k__BackingField
Entry: 9
Data: 14
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: true
- Name: _fieldAttributes
Entry: 7
Data: 18|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 1
- Name:
Entry: 7
Data: 19|UnityEngine.SerializeField, UnityEngine.CoreModule
- Name:
Entry: 8
Data:
- 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: amountUp
- Name: $v
Entry: 7
Data: 20|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: amountUp
- Name: <UserType>k__BackingField
Entry: 9
Data: 6
- Name: <SystemType>k__BackingField
Entry: 9
Data: 6
- Name: <SyncMode>k__BackingField - Name: <SyncMode>k__BackingField
Entry: 7 Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
@@ -364,7 +322,55 @@ MonoBehaviour:
Data: false Data: false
- Name: _fieldAttributes - Name: _fieldAttributes
Entry: 7 Entry: 7
Data: 21|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib Data: 20|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: amountUp
- Name: $v
Entry: 7
Data: 21|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: amountUp
- Name: <UserType>k__BackingField
Entry: 9
Data: 19
- Name: <SystemType>k__BackingField
Entry: 9
Data: 19
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 22|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name: - Name:
Entry: 12 Entry: 12
Data: 0 Data: 0
@@ -388,22 +394,16 @@ MonoBehaviour:
Data: loopOffset Data: loopOffset
- Name: $v - Name: $v
Entry: 7 Entry: 7
Data: 22|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor Data: 23|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField - Name: <Name>k__BackingField
Entry: 1 Entry: 1
Data: loopOffset Data: loopOffset
- Name: <UserType>k__BackingField - Name: <UserType>k__BackingField
Entry: 7 Entry: 9
Data: 23|System.RuntimeType, mscorlib Data: 11
- Name:
Entry: 1
Data: System.Int32, mscorlib
- Name:
Entry: 8
Data:
- Name: <SystemType>k__BackingField - Name: <SystemType>k__BackingField
Entry: 9 Entry: 9
Data: 23 Data: 11
- Name: <SyncMode>k__BackingField - Name: <SyncMode>k__BackingField
Entry: 7 Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
@@ -434,6 +434,108 @@ MonoBehaviour:
- Name: - Name:
Entry: 8 Entry: 8
Data: Data:
- Name:
Entry: 7
Data:
- Name: $k
Entry: 1
Data: jumps
- Name: $v
Entry: 7
Data: 25|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: jumps
- Name: <UserType>k__BackingField
Entry: 7
Data: 26|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: System.Single[], mscorlib
- Name:
Entry: 8
Data:
- Name: <SystemType>k__BackingField
Entry: 9
Data: 26
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>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: jumpsIndex
- Name: $v
Entry: 7
Data: 28|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: jumpsIndex
- Name: <UserType>k__BackingField
Entry: 9
Data: 11
- Name: <SystemType>k__BackingField
Entry: 9
Data: 11
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 29|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: - Name:
Entry: 13 Entry: 13
Data: Data:

View File

@@ -2,33 +2,59 @@
using Marro.PacManUdon; using Marro.PacManUdon;
using System; using System;
using System.Drawing.Text; using System.Drawing.Text;
using TMPro;
using UnityEngine; using UnityEngine;
using UnityEngine.UI;
using VRC.SDKBase;
enum TestBallMode
{
UseNetworkTime,
UseNetworkDt,
UseUnityDt,
}
public class TestBall : SyncedObject public class TestBall : SyncedObject
{ {
[SerializeField] private NetworkManager networkManager;
[SerializeField] private Transform start; [SerializeField] private Transform start;
[SerializeField] private Transform end; [SerializeField] private Transform end;
[SerializeField] private TestBallMode mode;
private NetworkManager networkManager;
private const int LoopTimeMs = 1000; private const int LoopTimeMs = 1000;
private const float MaxUp = 0.7f; private const float MaxUp = 0.7f;
private const float UpPerPress = 0.4f; private const float UpPerPress = 0.4f;
private const float DownPerSecond = 1; private const float DownPerSecond = 1;
private float sumOfDt;
private float amountUp = 0; private float amountUp = 0;
private int loopOffset = 0; private int loopOffset = 0;
private void Start() private float[] jumps;
private int jumpsIndex;
public void Initialize(NetworkManager networkManager)
{ {
networkManager.Initialize(); this.networkManager = networkManager;
sumOfDt = networkManager.SyncedTime;
jumps = new float[10];
jumpsIndex = 0;
} }
public override void FixedUpdate() public override void SyncedUpdate()
{ {
DeltaUp(-DownPerSecond * Dt); SetProgress(GetProgress()); // A quick test that these methods work correctly
DeltaUp(-DownPerSecond * networkManager.Dt);
UpdateProgress();
float progress = GetProgress(); float progress = GetProgress();
transform.position = Vector3.Lerp(start.position, end.position, progress) + amountUp * MaxUp * Vector3.up;; transform.position = Vector3.Lerp(start.position, end.position, progress) + amountUp * MaxUp * Vector3.up;
} }
private void DeltaUp(float delta) private void DeltaUp(float delta)
@@ -36,35 +62,74 @@ public class TestBall : SyncedObject
amountUp = Mathf.Clamp(amountUp + delta, 0, 1); amountUp = Mathf.Clamp(amountUp + delta, 0, 1);
} }
private void Jump()
{
DeltaUp(UpPerPress);
jumps[jumpsIndex++] = GetProgress();
jumps[jumpsIndex++] = amountUp;
if (jumpsIndex == jumps.Length)
{
jumpsIndex = 0;
}
}
private void SetProgress(float progress) private void SetProgress(float progress)
{ {
var currentTimestamp = networkManager.GetTimestamp(networkManager.CurrentTimeTicks); var currentTimestamp = GetCurrentTimestamp();
loopOffset = (int)(currentTimestamp - progress * LoopTimeMs); loopOffset = (int)(currentTimestamp - progress * LoopTimeMs);
} }
private float GetProgress() private float GetProgress()
{ {
var currentTimestamp = networkManager.GetTimestamp(networkManager.CurrentTimeTicks); 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 ((int)currentTimestamp - loopOffset) % LoopTimeMs / (float)LoopTimeMs; // "uint % int" is not exposed, I love working in Udon
} }
private uint GetCurrentTimestamp()
{
switch (mode)
{
case TestBallMode.UseNetworkTime:
return NetworkManager.TimeToTimestamp(networkManager.SyncedTime);
case TestBallMode.UseNetworkDt:
case TestBallMode.UseUnityDt:
return NetworkManager.TimeToTimestamp(sumOfDt);
default:
Debug.LogError($"({nameof(TestBall)}) Unknown mode {mode}!");
return 0;
}
}
private void UpdateProgress()
{
switch (mode)
{
case TestBallMode.UseNetworkDt:
sumOfDt += networkManager.Dt;
break;
case TestBallMode.UseUnityDt:
if (!networkManager.IsEventUpdate)
{
sumOfDt += Time.fixedDeltaTime;
}
break;
}
}
public void UpButtonPressed() public void UpButtonPressed()
{ {
DeltaUp(UpPerPress); Jump();
Debug.Log($"({nameof(TestBall)}) Up button pressed, jumped up at {GetProgress()} to {amountUp}."); Debug.Log($"({nameof(TestBall)}) Up button pressed, jumped up at {GetProgress()} to {amountUp}.");
networkManager.SendEvent((NetworkEventType)1);
}
public void SyncButtonPressed()
{
networkManager.SendEvent((NetworkEventType)0);
Debug.Log($"({nameof(TestBall)}) Sync button pressed, synced at progress {GetProgress()} and amountUp {amountUp}.");
} }
public override void AppendSyncedData(byte[][] data, ref int index, NetworkEventType eventType) public override void AppendSyncedData(byte[][] data, ref int index, NetworkEventType eventType)
{ {
if (eventType == 0) if (eventType == 0)
{ {
Debug.Log($"({nameof(TestBall)}) Sending sync data at progress {GetProgress()} and amountUp {amountUp}.");
data[index++] = BitConverter.GetBytes(amountUp); data[index++] = BitConverter.GetBytes(amountUp);
data[index++] = BitConverter.GetBytes(GetProgress()); data[index++] = BitConverter.GetBytes(GetProgress());
} }
@@ -81,10 +146,26 @@ public class TestBall : SyncedObject
} }
else else
{ {
DeltaUp(UpPerPress); Jump();
Debug.Log($"({nameof(TestBall)}) Received up event, jumped up at {GetProgress()} to {amountUp}."); Debug.Log($"({nameof(TestBall)}) Received up event, jumped up at {GetProgress()} to {amountUp}.");
} }
return true; return true;
} }
public void WriteDebugOutput(TMP_InputField debugOutput)
{
string jumpsText = "";
for (int i = 0; i < jumps.Length; i += 2)
{
jumpsText += $"{i/2}. ({jumps[i]}, {jumps[i + 1]}), ";
}
debugOutput.text += $"{nameof(TestBall)} {mode}:\n" +
$"Progress: {GetProgress()}\n" +
$"Up: {amountUp}\n" +
$"SumOfDt: {sumOfDt}\n" +
$"Jumps: {jumpsText}\n" +
$"\n";
}
} }

View File

@@ -0,0 +1,244 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c333ccfdd0cbdbc4ca30cef2dd6e6b9b, type: 3}
m_Name: TestBallManager
m_EditorClassIdentifier:
serializedUdonProgramAsset: {fileID: 11400000, guid: 007782662b6528e4a855cc8fb5cca273, type: 2}
udonAssembly:
assemblyError:
sourceCsScript: {fileID: 11500000, guid: 40fc654db4dfd4f4c9cdf45903f134a3, type: 3}
scriptVersion: 2
compiledVersion: 2
behaviourSyncMode: 0
hasInteractEvent: 0
scriptID: 8109348476653380640
serializationData:
SerializedFormat: 2
SerializedBytes:
ReferencedUnityObjects: []
SerializedBytesString:
Prefab: {fileID: 0}
PrefabModificationsReferencedUnityObjects: []
PrefabModifications: []
SerializationNodes:
- Name: fieldDefinitions
Entry: 7
Data: 0|System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[UdonSharp.Compiler.FieldDefinition,
UdonSharp.Editor]], mscorlib
- Name: comparer
Entry: 7
Data: 1|System.Collections.Generic.GenericEqualityComparer`1[[System.String,
mscorlib]], mscorlib
- Name:
Entry: 8
Data:
- Name:
Entry: 12
Data: 3
- Name:
Entry: 7
Data:
- Name: $k
Entry: 1
Data: testBalls
- Name: $v
Entry: 7
Data: 2|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: testBalls
- Name: <UserType>k__BackingField
Entry: 7
Data: 3|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: TestBall[], Assembly-CSharp
- Name:
Entry: 8
Data:
- Name: <SystemType>k__BackingField
Entry: 7
Data: 4|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: UnityEngine.Component[], UnityEngine.CoreModule
- Name:
Entry: 8
Data:
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: true
- Name: _fieldAttributes
Entry: 7
Data: 5|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 1
- Name:
Entry: 7
Data: 6|UnityEngine.SerializeField, UnityEngine.CoreModule
- Name:
Entry: 8
Data:
- 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: networkManager
- Name: $v
Entry: 7
Data: 7|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: networkManager
- Name: <UserType>k__BackingField
Entry: 7
Data: 8|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: Marro.PacManUdon.NetworkManager, Assembly-CSharp
- Name:
Entry: 8
Data:
- Name: <SystemType>k__BackingField
Entry: 7
Data: 9|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: VRC.Udon.UdonBehaviour, VRC.Udon
- Name:
Entry: 8
Data:
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: true
- Name: _fieldAttributes
Entry: 7
Data: 10|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 1
- Name:
Entry: 7
Data: 11|UnityEngine.SerializeField, UnityEngine.CoreModule
- Name:
Entry: 8
Data:
- 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: debugOutput
- Name: $v
Entry: 7
Data: 12|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: debugOutput
- Name: <UserType>k__BackingField
Entry: 7
Data: 13|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: TMPro.TMP_InputField, Unity.TextMeshPro
- Name:
Entry: 8
Data:
- Name: <SystemType>k__BackingField
Entry: 9
Data: 13
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: true
- Name: _fieldAttributes
Entry: 7
Data: 14|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 1
- Name:
Entry: 7
Data: 15|UnityEngine.SerializeField, UnityEngine.CoreModule
- Name:
Entry: 8
Data:
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 366d931a37811ce47be572127126c17b
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,66 @@

using Marro.PacManUdon;
using TMPro;
using UdonSharp;
using UnityEngine;
using UnityEngine.UI;
using VRC.SDKBase;
using VRC.Udon;
public class TestBallManager : UdonSharpBehaviour
{
[SerializeField] TestBall[] testBalls;
[SerializeField] NetworkManager networkManager;
[SerializeField] private TMP_InputField debugOutput;
void Start()
{
networkManager.Initialize();
foreach (var testBall in testBalls)
{
testBall.Initialize(networkManager);
}
}
public void Update()
{
if (debugOutput == null)
{
return;
}
debugOutput.text = "";
networkManager.WriteDebugOutput(debugOutput);
foreach (var testBall in testBalls)
{
testBall.WriteDebugOutput(debugOutput);
}
}
public void ResetButtonPressed()
{
Start();
}
public void UpButtonPressed()
{
foreach (var testBall in testBalls)
{
testBall.UpButtonPressed();
}
networkManager.SendEvent((NetworkEventType)1);
}
public void SyncButtonPressed()
{
if (VRCPlayerApi.GetPlayerCount() == 1)
{
networkManager.SimulateSyncToTimestamp(NetworkManager.TimeToTimestamp(networkManager.SyncedTime - 0.5f));
}
else
{
networkManager.SendEvent((NetworkEventType)0);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 40fc654db4dfd4f4c9cdf45903f134a3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: