Search Unity

Question Synced independent Timer

Discussion in 'Netcode for GameObjects' started by Sofibab_, Jan 4, 2022.

  1. Sofibab_

    Sofibab_

    Joined:
    Jan 4, 2022
    Posts:
    1
    Hi there!

    So I'm trying to sync audio across clients. To do this I need to have a timer that keeps track of the current audio progress on the server that clients can then sync to when joining or if they get out of sync during the game:



    I've created a TimeKeeper script that is shared by all clients. This has a button that allows the server to start the time.

    Each player then has a TimerKeeperClient script. This has a button that should get the current time from the server and sync it to the local TimeKeeper. I've tried doing this using the example from the docs for creating a synced event and after that by using a NetworkVariable. Unfortunately I can't seem to get the time to sync properly, there is always quite a bit of delay when i simulate latency.

    Does anyone know of a better method for doing this? I can't use NetworkTime because that doesn't stay true to the audio playing on the server.

    Hope to hear from you! :)

    TimeKeeper
    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using Unity.Netcode;
    4. using UnityEngine.UI;
    5.  
    6. public class TimeKeeper : NetworkBehaviour
    7. {
    8.  
    9.    public static TimeKeeper Instance;
    10.  
    11.    private void Awake()
    12.    {
    13.        if (Instance == null)
    14.            Instance = this;
    15.    }
    16.  
    17.    public float time = -1f;
    18.  
    19.    // Update is called once per frame
    20.    void FixedUpdate()
    21.     {
    22.        if (time == -1f)
    23.            return;
    24.  
    25.        time += Time.fixedDeltaTime;
    26.     }
    27.  
    28.    void OnGUI()
    29.    {
    30.        GUILayout.BeginArea(new Rect(10, 400, 300, 300));
    31.  
    32.        if (IsServer)
    33.        {
    34.            if (GUILayout.Button("Start Server Time"))
    35.            {
    36.                time = 0f;
    37.            }
    38.        }
    39.  
    40.        GUILayout.Label("Timer: " + time);
    41.  
    42.        GUILayout.EndArea();
    43.    }
    44. }
    45.  
    TimerKeeperClient
    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using Unity.Netcode;
    4.  
    5. public class TimeKeeperClient : NetworkBehaviour
    6. {
    7.    public float lag = -1f;
    8.  
    9.    public void StartClientTime()
    10.    {
    11.        var time = NetworkManager.LocalTime.Time;
    12.        CreateSyncedEventServerRpc(time);
    13.    }
    14.  
    15.    [ServerRpc]
    16.    private void CreateSyncedEventServerRpc(double time)
    17.    {
    18.        CreateSyncedEventClientRpc(time, TimeKeeper.Instance.time); // Call a client RPC to also create the effect on each client.
    19.    }
    20.  
    21.    [ClientRpc]
    22.    private void CreateSyncedEventClientRpc(double time, float _timer)
    23.    {
    24.        if (!IsOwner)
    25.            return;
    26.  
    27.        lag = (float)(time - NetworkManager.ServerTime.Time);
    28.        TimeKeeper.Instance.time = _timer - lag;
    29.  
    30.    }
    31.  
    32.    private void OnGUI()
    33.    {
    34.        if (!IsOwner || IsServer)
    35.            return;
    36.  
    37.        GUILayout.BeginArea(new Rect(400, 400, 300, 300));
    38.  
    39.        if (GUILayout.Button("Sync Time"))
    40.        {
    41.            StartClientTime();
    42.        }
    43.  
    44.        GUILayout.Label("Lag: " + lag);
    45.  
    46.        GUILayout.EndArea();
    47.    }
    48. }
    49.