using librsync.net; using Marro.PacManUdon; using System; using System.Drawing.Text; using TMPro; using UnityEngine; using UnityEngine.UI; using VRC.SDKBase; enum TestBallMode { UseNetworkTime, UseNetworkDt, UseUnityDt, } public class TestBall : SyncedObject { [SerializeField] private Transform start; [SerializeField] private Transform end; [SerializeField] private TestBallMode mode; private NetworkManager networkManager; private const int LoopTimeMs = 1000; private const float MaxUp = 0.7f; private const float UpPerPress = 0.4f; private const float DownPerSecond = 1; private float sumOfDt; private float amountUp = 0; private int loopOffset = 0; private float[] jumps; private int jumpsIndex; public void Initialize(NetworkManager networkManager) { this.networkManager = networkManager; sumOfDt = networkManager.SyncedTime; jumps = new float[10]; jumpsIndex = 0; } public override void SyncedUpdate() { SetProgress(GetProgress()); // A quick test that these methods work correctly DeltaUp(-DownPerSecond * networkManager.Dt); UpdateProgress(); float progress = GetProgress(); transform.position = Vector3.Lerp(start.position, end.position, progress) + amountUp * MaxUp * Vector3.up; } private void DeltaUp(float delta) { 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) { var currentTimestamp = GetCurrentTimestamp(); loopOffset = (int)(currentTimestamp - progress * LoopTimeMs); } private float GetProgress() { 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 } 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() { Jump(); Debug.Log($"({nameof(TestBall)}) Up button pressed, jumped up at {GetProgress()} to {amountUp}."); } public override void AppendSyncedData(byte[][] data, ref int index, NetworkEventType eventType) { 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(GetProgress()); } } public override bool SetSyncedData(byte[] data, ref int index, NetworkEventType eventType) { if (eventType == 0) { amountUp = BitConverter.ToSingle(data, index); SetProgress(BitConverter.ToSingle(data, index + 4)); Debug.Log($"({nameof(TestBall)}) Received sync event, synced to progress {GetProgress()} and amountUp {amountUp}."); index += 8; } else { Debug.Log($"({nameof(TestBall)}) Received up event, jumped up at {GetProgress()} from {amountUp}."); Jump(); Debug.Log($"({nameof(TestBall)}) Received up event, jumped up at {GetProgress()} to {amountUp}."); } 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"; } }