using Marro.PacManUdon; using Newtonsoft.Json.Linq; using UdonSharp; using UnityEngine; using VRC.SDKBase; using VRC.Udon; public class NetworkManagerSyncTester : UdonSharpBehaviour { [SerializeField] NetworkManager networkManager1; [SerializeField] GridMover[] gridMovers1; [SerializeField] NetworkManager networkManager2; [SerializeField] GridMover[] gridMovers2; [SerializeField] Animator debugImageToIndicateSynced; private int[] captureTimes = new int[1000]; private Vector2[][] positionCaptures = new Vector2[1000][]; private int ownerIndex = -1; private int remoteIndex = 0; private int previousCaptureTime = -1; public void Update() { if (!networkManager1.Synced || !networkManager2.Synced) { ownerIndex = -1; remoteIndex = 0; return; } var ownerTime = networkManager1.SyncedTimeTicks; if (ownerTime > previousCaptureTime) { IncrementIndex(ref ownerIndex); captureTimes[ownerIndex] = ownerTime; previousCaptureTime = ownerTime; positionCaptures[ownerIndex] = GetPositions(gridMovers1); } var remoteTime = networkManager2.SyncedTimeTicks; while (captureTimes[remoteIndex] < remoteTime && remoteIndex != ownerIndex) { DiscardCapture(); } //Debug.Log($"ownerTime: {ownerTime}, remoteTime: {remoteTime}, ownerIndex: {ownerIndex} ({captureTimes[ownerIndex]}), remoteIndex: {remoteIndex} ({captureTimes[remoteIndex]})"); if (captureTimes[remoteIndex] == remoteTime) { bool equal = IsEqual(remoteIndex, remoteTime); SetIndicator(equal); DiscardCapture(); } } private void DiscardCapture() { positionCaptures[remoteIndex] = null; IncrementIndex(ref remoteIndex); } private bool IsEqual(int index, int time) { var equal = true; var positions1 = positionCaptures[index]; var positions2 = GetPositions(gridMovers2); for (int i = 0; i < positions1.Length; i++) { var gridMover1 = gridMovers1[i]; var gridMover1Position = positions1[i]; var gridMover2 = gridMovers2[i]; var gridMover2Position = positions2[i]; if (gridMover1Position != gridMover2Position) { Debug.LogWarning($"{nameof(NetworkManagerSyncTester)} Desync found at {time} in {gridMover1.name}:\n {gridMover1Position} (local) != {gridMover2Position} (remote)"); //networkManager1.Pause(); //networkManager2.Pause(); equal = false; } } return equal; } private void SetIndicator(bool value) { if (debugImageToIndicateSynced != null) { debugImageToIndicateSynced.SetFloat("Color", value ? 1 : 0); } } private static Vector2[] GetPositions(GridMover[] gridMovers) { var length = gridMovers.Length; var positions = new Vector2[length]; for (int i = 0; i < length; i++) { positions[i] = gridMovers[i].GetPosition(); } return positions; } private void IncrementIndex(ref int index) { if (index >= positionCaptures.Length - 1) { index = 0; } else { index++; } } }