1
\$\begingroup\$

Edit

Okay, so I partially solved the problem by adding a rigid body component to the capsule. I read somewhere that apparently you have to have one in order to move on the server.

Problem 2

The next problem I have is that I can now move a capsule that is spawned by the client fine and the host can move it as well as many times as they like. The problem I am getting now is that when the host spawns a capsule the client cannot move it at all and I get a sort of glitch effect on the client side and the capsule still doesn't move on the host side. Is there a reason why it would only work one way and not the other way around? I thought at first it might have to do with Spawn vs SpawnWithClientAuthority but that doesn't seem to make a difference.


Project Summary

I have a pretty simple multiplayer project, all I want to do is have one player host and the other join as a client. Once they are joined together the two players can spawn a capsule and then when the user clicks on a capsule. They should be able to pick it up and move it around the scene and the other player should be able to see this action. I can get both players to connect to the server and spawn their own capsule and both players can see this. The movement script is done as well. However, it is only transmitted on the host side. When the client picks up the object it does not update on the server.

Problem

I have done a bit of debugging and have found that when I call the command on the client it is not being executed at all through line breaks and simple debug statements.

Code

public void OnInputClicked(InputClickedEventData eventData)
    {
        Debug.Log("clicked");
        if (isLocalPlayer)
        {
            if (Physics.Raycast(transform.position, direction: transform.forward, hitInfo: out hit, maxDistance: range))
            {
                Debug.Log("Hit capsule");

                objectID = GameObject.Find(hit.transform.name);
                objNetId = objectID.GetComponent<NetworkIdentity>();
                playerIDThatClicked = player.GetComponent<NetworkIdentity>();


                CmdAssignAuthority(objNetId, playerIDThatClicked);
                Debug.Log("grabbed");

            }
            else
            {
                //if we are releasing the object we want to unassign our authority
                if (objNetId != null)
                {
                    CmdAssignAuthority(objNetId, playerIDThatClicked);

                    objNetId = null;
                    Debug.Log("released");
                }
            }
        }


    }

[Command]
    void CmdAssignAuthority(NetworkIdentity target, NetworkIdentity player)
    {
        Debug.Log("inside cmd");
        current = target.clientAuthorityOwner;
        playerconn = player.connectionToClient;


        if (current != null && current != playerconn)
        {
            Debug.Log("Had authority now removing and replacing");
            target.RemoveClientAuthority(current);

            target.AssignClientAuthority(playerconn);

        }
        else if (current != null)
        {
            Debug.Log("removing authority");
            target.RemoveClientAuthority(current);

        }
        else if (current == null)

        {
            Debug.Log("No authority, adding one now");
            target.AssignClientAuthority(playerconn);


        }
        else {
            Debug.Log("CmdAuthority error");
            target.RemoveClientAuthority(playerconn);

        }
    }

Question

Am I calling this command correctly? The script is attached to a player prefab and the capsule prefab contains a network id and a network transform. I am pretty new to Unet and this feels like a noob mistake.

\$\endgroup\$
  • \$\begingroup\$ Make sure your capsule has a NetworkTransform with the right TransformSyncMode \$\endgroup\$ – Coburn Sep 19 '17 at 18:22
  • \$\begingroup\$ Never thought to do authority like this though. Usually, you would just send the mouse coords to the server or the new capsule position and have the server update it and have propogate everywhere else instead of swapping authority. Is objNetId only set in the place you show in the code above? I have a feeling it isn't giving the correct value on one of the connected machines though I would have to run a test project to really verify the implementation of this function in the complex way you're using above \$\endgroup\$ – Coburn Sep 19 '17 at 18:31
  • \$\begingroup\$ objNetId isn't used anywhere else it is only initialized at the top of the script. I have another script that is a Tap to place paired with this. When you click you grab click again to let go. Should I set it to null after the command in the if ( objNetId != null) statement ? \$\endgroup\$ – Dtb49 Sep 19 '17 at 19:03
  • \$\begingroup\$ I am also developing this on the HoloLens so that is another pain in itself... \$\endgroup\$ – Dtb49 Sep 19 '17 at 19:05
0
\$\begingroup\$

EDIT:

If your objects have the same name I could see GameObject.find(hit.transform.name) giving you issues (use hit.transform.gameObject instead)


Original answer:

If I'm reading your logic right, CmdAssignAuthority written another way works as follows:

  • if (current != null && current != connectionToClient) set authority to connectionToClient
  • else if ( current == connectionToClient ) set to null (b/c current != null means it must be connection to client due to the first if statement)
  • else if ( current == null ) set to connectionToClient

I'm not entirely sure how often your OnInputClicked due to differences between AR devices but I'm going to assume something like this video. The logic in OnInputClicked can be psuedo-coded as:

  • if ( click and raycast hit ) it will do the above routine for that object
  • if ( click and miss and cached hit object ) it will do the same routine

This logic has a few potential errors:

  • Clicking twice with the same raycast outcome (hit or miss) is going to put the authority out of sync with who's actually clicking (a hit would be a release and a miss would set authority).
  • Because it only ever assigns authority with connectionToClient, the host client, when clicking, will assign authority to connectionToClient as well which is probably why you can never move it on the host.
  • The third case in your CmdAssignAuthority which your first if catches should never happen and makes it harder to read what's going on.

It looks like your logic is tangled up in CmdSetAuthority and potentially can break down in OnInputClicked if the clicker is not the connectionToClient. I suggest rewriting your logic so that it sends some sort of ID for the clicking player to the CmdSetAuthority instead of just toggling between null and connectionToClient

\$\endgroup\$
  • \$\begingroup\$ I will explain my logic here, 1st. if the object has an owner and that owner is not the player that clicked remove authority from the current owner and assign it to the player that clicked. 2nd Else if the object has an owner and that owner is the player that clicked (i.e. this is the 2nd click or the check if the player is dropping the object) we want to remove our authority over the object. 3rd or if the object doesn't have an owner (i.e. the first click) we want to grab that object. \$\endgroup\$ – Dtb49 Sep 20 '17 at 13:29
  • \$\begingroup\$ I edited the code to your suggestion and still have the same problem as before \$\endgroup\$ – Dtb49 Sep 20 '17 at 15:43
  • \$\begingroup\$ After a little more debugging, it actually only breaks when I spawn in a second capsule. So it doesn't matter who spawns the first one I have complete control over it, client or host. However, when I spawn a second one that is actually when the client loses control over the capsule and only the host can control it. @Coburn \$\endgroup\$ – Dtb49 Sep 20 '17 at 17:49
  • \$\begingroup\$ Ah, should have read closer that your script was on a player prefab and that connectionToClient was a built in and not custom. Knowing that I don't see anything wrong with your logic... If your objects have the same name I could see GameObject.find(hit.transform.name) giving you issues (use hit.transform.gameObject instead?). Otherwise I got nothing \$\endgroup\$ – Coburn Sep 20 '17 at 18:01
  • \$\begingroup\$ Wow, that was it lol I've been scratching my head at this for days. \$\endgroup\$ – Dtb49 Sep 20 '17 at 18:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.