Command Function updates local SyncVar variable late on client

I have got a project where each character in the game has a target which they can cast spells upon. I also want the other players in the game to be aware of which target every player is currently targeting at the moment (think WoW, target of target).

I am currently struggling with the networking part for each client. The code I have written works well for the host, but for the client, it takes a few updates before one’s target has been set. Below, I have pasted two pictures illustrating my code, cut away some unnecessary parts that aren’t crucial to the problem.

This is the simple part of a Player connection script, which on connecting, instantiates a character prefab and gets authority over it.

void Start()
{
    if (!isLocalPlayer)
        return;

    CmdSpawnCharacter();
}

[Command]
private void CmdSpawnCharacter()
{
    GameObject go = Instantiate(myCharacterPrefab, this.transform);

    NetworkServer.SpawnWithClientAuthority(go, connectionToClient);
}

The next part of code is part of my Character Script. I have understood that I can set the target variable as a Syncvar, so that the server automatically updates which target is being targeted by that character for each client on the server. So whenever I left mouse click on a targetable target (private void RaycastNewTarget()), I need to tell the server that I am switching target. Hence the function CmdSetTarget().

(All targets that are targetable have a Network Identity, so I can pass a GameObject as variable to Cmd function)

If I have hit a target, the function CmdSetTarget() prints out the true if-statement, but on the third line in the if-statement of RaycastNewTarget() I get an error that myTarget is null. However, if I try again straight after, it will work, since myTarget has been set to what I tried clicking the first time.
It seems as if the server updates my own target as if it was a client as well, a few frames later.

[SyncVar]
private GameObject myTarget;

void Update()
{
    if (!hasAuthority)
        return;
        
    if (Input.GetMouseButtonDown(0))
    {
        RaycastNewTarget();
    }
}
    
private void RaycastNewTarget()
{
    RaycastHit hit;
    Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    LayerMask layerMask = LayerMask.GetMask("Targetable");

    if (Physics.Raycast(ray, out hit, 100.0f, layerMask))
    {
        CmdSetTarget(hit.collider.transform.gameObject);

        myTarget.GetComponentInChildren<Projector>().enabled = true;

        SetTargetHUD();
    }
}
    
[Command]
private void CmdSetTarget(GameObject aTarget)
{
    myTarget = aTarget;

    if (myTarget)
        Debug.Log("Target is: " + myTarget.name);
    else
        Debug.Log("Target is null now!");
}

I am a bit unsure how I should solve this problem. Should I set myTarget to the raycast hit first, and then afterwards alert the CmdSetTarget() again, basically doing the same code? Or should I rewrite it to another way?

Hope it was clear enough. Cheers :slight_smile:

First of all, please do not post code as images. It makes it impossible to quote your code in an answer. It also wastes a lot of memory.

Of course it will take some time until the command is actually send to the server and until the sync event is send back to your client. However i don’t quite see the issue here. It seems you just want to enable the projector locally on your client. Why don’t you just use the object reference you already have? If you don’t want to do that for some reason you can use a ClientRPC or TargetRPC from your command method on the server to basically get a “callback” when the command has been processed. Though keep in mind that syncvars can actually define a hook which is executed when the variable is updated on that client.