Using network time to create a synced event

Hello,
right now I am trying to create a syncronized event using a script from the documentation. It is the example 2 from this document

Herethe code:

using System.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Assertions;

public class SyncedEventExample : NetworkBehaviour
{
    public GameObject ParticleEffect;

    // Called by the client to create a synced particle event at its own position.
    public void ClientCreateSyncedEffect()
    {
        Assert.IsTrue(IsOwner);
        var time = NetworkManager.LocalTime.Time;
        CreateSyncedEffectServerRpc(time);
        StartCoroutine(WaitAndSpawnSyncedEffect(0)); // Create the effect immediately locally.
    }

    private IEnumerator WaitAndSpawnSyncedEffect(float timeToWait)
    {
        // Note sometimes the timeToWait will be negative on the server or the receiving clients if a message got delayed by the network for a long time. This usually happens only in rare cases. Custom logic could be implemented to deal with that scenario.
        if (timeToWait > 0)
        {
            yield return new WaitForSeconds(timeToWait);
        }

        Instantiate(ParticleEffect, transform.position, Quaternion.identity);
    }

    [ServerRpc]
    private void CreateSyncedEffectServerRpc(double time)
    {
        CreateSyncedEffectClientRpc(time); // Call a client RPC to also create the effect on each client.
        var timeToWait = time - NetworkManager.ServerTime.Time;
        StartCoroutine(WaitAndSpawnSyncedEffect((float)timeToWait)); // Create the effect on the server but wait for the right time.
    }

    [ClientRpc]
    private void CreateSyncedEffectClientRpc(double time)
    {
        // The owner already created the effect so skip them.
        if (IsOwner == false)
        {
            var timeToWait = time - NetworkManager.ServerTime.Time;
            StartCoroutine(WaitAndSpawnSyncedEffect((float)timeToWait)); // Create the effect on the client but wait for the right time.
        }
    }
}

The problem is, if I run the code on the client, then nothing happens. If I run the code on the host, I use p2p, then the event happens 2x on the host and 1x on the client.
Maybe the comments in the code are also misleading. What am I doing wrong?

Hi @Nivagia , could it be that this script is on an object on which you don’t have ownership? By default, ServerRpcs require to be called from a NetworkObject that is owned by the client.
So you’ll get an error when trying to call this rpc as a client that is not the host.
Adding (RequireOwnership = false) parameter to your [ServerRPC] and [ClientRPC] attributes should do the trick

I figuered, that the example code on the unity documentation must be wrong.
This is my code now:

using System.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Assertions;
using UnityEngine.Events;

public class SyncedGameStart : NetworkBehaviour
{
    public UnityEvent GameStart;

    // Called by the client to create a synced event at its own position.
    public void ClientCreateSyncedEvent()
    {
        if (IsHost)
        {
            return;
        }
        var time = NetworkManager.LocalTime.Time;
        CreateSyncedEventServerRpc(time);
        StartCoroutine(WaitAndSpawnSyncedEvent(0));
        // Create the event immediately locally.
        Debug.Log("Client created synced event");
    }

    private IEnumerator WaitAndSpawnSyncedEvent(float timeToWait)
    {
        // Note sometimes the timeToWait will be negative on the server or the receiving clients if a message got delayed by the network for a long time. This usually happens only in rare cases. Custom logic could be implemented to deal with that scenario.
        Debug.Log("Time to wait is: " + timeToWait);

        if (timeToWait > 0)
        {
            yield return new WaitForSeconds(timeToWait);
        }

        Debug.Log("Invoke GameStartNow: " + System.DateTime.Now.ToString() +":"+ System.DateTime.Now.Millisecond.ToString());
        GameStart?.Invoke();
    }

    [ServerRpc(RequireOwnership = false)]
    private void CreateSyncedEventServerRpc(double time)
    {
        CreateSyncedEventClientRpc(time);
        // Call a client RPC to also create the event on each client.
        var timeToWait = time - NetworkManager.ServerTime.Time;
        StartCoroutine(WaitAndSpawnSyncedEvent((float)timeToWait)); // Create the event on the server but wait for the right time.
    }

    [ClientRpc]
    private void CreateSyncedEventClientRpc(double time)
    {
        // The owner already created the event so skip them.
        if (IsHost)
        {
            return;
        }
        var timeToWait = time - NetworkManager.ServerTime.Time;
        StartCoroutine(WaitAndSpawnSyncedEvent((float)timeToWait)); // Create the event on the client but wait for the right time. 
    }
}

I now have the problem, that when I add a little delay to the network, the timeToWait is always a negative number and the event is triggered right away.