Objects not syncing position properly between server and client

I have this code here, attached to my player:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

public class gunControllerScript : NetworkBehaviour {

    [SyncVar]
    public GameObject currentGun = null;

    public Transform gunHolder;
    public RawImage gunImage; //UI Element for the gun's icon
    public Text ammoText; //UI Element for the ammo text (Example: 12/30)
    public Text weaponName; //The text box for the name of the weapon to appear in
    private string[] ammos;



    // Use this for initialization
    void Start () {
        ammos = new string[2];
        InvokeRepeating("updateAmmoCount", .5f, .5f);
    }
   
    // Update is called once per frame
    void Update () {
        /*
        if(currentGun != null)
        {
            currentGun.transform.position = gunHolder.transform.position;
            currentGun.transform.rotation = gunHolder.transform.rotation;
        }
        */
        if (isLocalPlayer)
        {
           
            if (Input.GetButtonDown("Fire1"))
            {
                if (currentGun != null)
                {
                    currentGun.SendMessage("CmdFirePrimary");
                    ammos = currentGun.GetComponent<GunScript>().GetAmmo();
                    ammoText.text = ammos[0] + "/" + ammos[1];
                }
            }
            if (Input.GetButtonDown("Fire2"))
            {
                if (currentGun != null)
                {
                    currentGun.SendMessage("CmdFireSecondary");
                    ammos = currentGun.GetComponent<GunScript>().GetAmmo();
                    ammoText.text = ammos[0] + "/" + ammos[1];
                }
            }
            if (Input.GetButtonDown("Reload"))
            {
                if (currentGun != null)
                {
                    currentGun.SendMessage("Reload");
                    ammos = currentGun.GetComponent<GunScript>().GetAmmo();
                    ammoText.text = ammos[0] + "/" + ammos[1];
                }
            }
        }
    }

    [Command]
    public void CmdPickupWeapon(GameObject w)
    {
        if (currentGun != null)
        {
            currentGun.GetComponent<Rigidbody>().useGravity = true; //Make sure the currently-held weapon will drop to the ground
            currentGun.GetComponent<Rigidbody>().isKinematic = false; //Make sure the currently-held weapon can move
            currentGun.transform.SetParent(null); //Drop it from the hand (no longer relative to the hand, relative to the world instead)
            currentGun.GetComponent<NetworkTransform>().enabled = true; //transformSyncMode = NetworkTransform.TransformSyncMode.SyncRigidbody3D;
            foreach (BoxCollider bc in currentGun.GetComponents<BoxCollider>())
            {
                bc.enabled = true; //Make sure it can be picked up and/or kicked around
            }
            foreach (BoxCollider b in currentGun.GetComponentsInChildren<BoxCollider>())
            {
                b.enabled = true;
            }
            currentGun.GetComponent<NetworkIdentity>().RemoveClientAuthority(gameObject.GetComponent<NetworkIdentity>().connectionToClient);

        }
        currentGun = w;
        currentGun.transform.SetParent(gunHolder); //Attach the newly picked up weapon to the hand, and move it there
        currentGun.transform.position = gunHolder.transform.position;
        currentGun.transform.rotation = gunHolder.transform.rotation;
        currentGun.GetComponent<Rigidbody>().useGravity = false;
        currentGun.GetComponent<Rigidbody>().isKinematic = true;
        currentGun.GetComponent<NetworkIdentity>().AssignClientAuthority(gameObject.GetComponent<NetworkIdentity>().connectionToClient);
        //currentGun.GetComponent<NetworkTransform>().enabled = false; //transformSyncMode = NetworkTransform.TransformSyncMode.SyncTransform;
        try
        {
            gunImage.texture = currentGun.GetComponent<GunScript>().GetGunIcon();
            gunImage.material = null;
        }
        catch
        {
            Debug.Log("Failed image!");
        }
        try
        {
            weaponName.text = currentGun.GetComponent<GunScript>().GetName();
        }
        catch
        {
            Debug.Log("Failed text!");
        }

        foreach (BoxCollider bc in currentGun.GetComponents<BoxCollider>())
        {
            bc.enabled = false; //Make sure it doesn't give us false weapon pickups, and doesn't continue to collide with the player
        }

        foreach (BoxCollider b in currentGun.GetComponentsInChildren<BoxCollider>()){
            b.enabled = false;
        }
    }

    public void updateAmmoCount()
    {
        if (currentGun != null)
        {
            ammos = currentGun.GetComponent<GunScript>().GetAmmo();
            ammoText.text = ammos[0] + "/" + ammos[1];
        }

    }

    public void OnTriggerStay(Collider col)
    {
        if (Input.GetButtonDown("Interact"))
        {
            if (isLocalPlayer)
            {
                if (col.gameObject.CompareTag("Weapon"))
                {
                    CmdPickupWeapon(col.gameObject);
                    /*
                    if (currentGun != null)
                    {
                        currentGun.GetComponent<Rigidbody>().useGravity = true; //Make sure the currently-held weapon will drop to the ground
                        currentGun.GetComponent<Rigidbody>().isKinematic = false; //Make sure the currently-held weapon can move
                        currentGun.transform.SetParent(null); //Drop it from the hand (no longer relative to the hand, relative to the world instead)
                        currentGun.GetComponent<NetworkTransform>().transformSyncMode = NetworkTransform.TransformSyncMode.SyncRigidbody3D;
                        foreach (BoxCollider bc in currentGun.GetComponents<BoxCollider>())
                        {
                            bc.enabled = true; //Make sure it can be picked up and/or kicked around
                        }
                    }
                    currentGun = col.gameObject;
                    currentGun.transform.SetParent(gunHolder); //Attach the newly picked up weapon to the hand, and move it there
                    currentGun.transform.position = gunHolder.transform.position;
                    currentGun.transform.rotation = gunHolder.transform.rotation;
                    currentGun.GetComponent<Rigidbody>().useGravity = false;
                    currentGun.GetComponent<Rigidbody>().isKinematic = true;
                    currentGun.GetComponent<NetworkTransform>().transformSyncMode = NetworkTransform.TransformSyncMode.SyncTransform;
                    foreach (BoxCollider bc in currentGun.GetComponents<BoxCollider>())
                    {
                        bc.enabled = false; //Make sure it doesn't give us false weapon pickups, and doesn't continue to collide with the player
                    }
                    */

                }
            }
        }
    }
}

It works fine locally. It even works fine when the server player picks up a gun, as the client sees the gun being held and yada yada. When the client picks up a gun, however, the server sees the client holding the gun, but the client still sees the gun on the ground. After a little bit, the gun floats over and gitches out in the player’s hand. When checking in the scene view, the gun actually doesn’t become a child of gunHolder like it should. Again, this is only when clients attempt to pick up guns. They can still see the ammo count, and still fire the gun. Any idea why the position isn’t showing up properly?

My Unet practice is a bit rusty, but I think you should get the desired results with this:

[Command]
public void CmdPickupWeapon(GameObject wep)
{
    RpcPickupWeapon(wep);
}

[ClientRpc]
public void RpcPickupWeapon(GameObject w)
{
    if (currentGun != null)
        {
            currentGun.GetComponent<Rigidbody>().useGravity = true; //Make sure the currently-held weapon will drop to the ground
            currentGun.GetComponent<Rigidbody>().isKinematic = false; //Make sure the currently-held weapon can move
            currentGun.transform.SetParent(null); //Drop it from the hand (no longer relative to the hand, relative to the world instead)
            currentGun.GetComponent<NetworkTransform>().enabled = true; //transformSyncMode = NetworkTransform.TransformSyncMode.SyncRigidbody3D;
            foreach (BoxCollider bc in currentGun.GetComponents<BoxCollider>())
            {
                bc.enabled = true; //Make sure it can be picked up and/or kicked around
            }
            foreach (BoxCollider b in currentGun.GetComponentsInChildren<BoxCollider>())
            {
                b.enabled = true;
            }
            currentGun.GetComponent<NetworkIdentity>().RemoveClientAuthority(gameObject.GetComponent<NetworkIdentity>().connectionToClient);
        }
        currentGun = w;
        currentGun.transform.SetParent(gunHolder); //Attach the newly picked up weapon to the hand, and move it there
        currentGun.transform.position = gunHolder.transform.position;
        currentGun.transform.rotation = gunHolder.transform.rotation;
        currentGun.GetComponent<Rigidbody>().useGravity = false;
        currentGun.GetComponent<Rigidbody>().isKinematic = true;
        currentGun.GetComponent<NetworkIdentity>().AssignClientAuthority(gameObject.GetComponent<NetworkIdentity>().connectionToClient);
        //currentGun.GetComponent<NetworkTransform>().enabled = false; //transformSyncMode = NetworkTransform.TransformSyncMode.SyncTransform;
        try
        {
            gunImage.texture = currentGun.GetComponent<GunScript>().GetGunIcon();
            gunImage.material = null;
        }
        catch
        {
            Debug.Log("Failed image!");
        }
        try
        {
            weaponName.text = currentGun.GetComponent<GunScript>().GetName();
        }
        catch
        {
            Debug.Log("Failed text!");
        }
        foreach (BoxCollider bc in currentGun.GetComponents<BoxCollider>())
        {
            bc.enabled = false; //Make sure it doesn't give us false weapon pickups, and doesn't continue to collide with the player
        }
        foreach (BoxCollider b in currentGun.GetComponentsInChildren<BoxCollider>()){
            b.enabled = false;
        }
}

I hope this helps you out a bit!
-PabloDiscobar

Awesome, thank you! Does that mean I’d want to do the same for taking damage, call an RPC through a CmdFunction? I appreciate the help!

Yes you could do that. Then your code will look something like this:

[Command]
public void CmdTakeDamage(int dmg, healthscript target)
{
    RpcTakeDamage(dmg, target);
}

[ClientRpc]
public void RpcTakeDamage(int dmg, healthscript target)
{
    target.PlayerHealth -= dmg;
}

Cool, thanks. Now the object works fine on the client, but the client sees the host’s gun flopping around (and sometimes the gun will freeze where the host was, and eventually come back to where the host moved after a few seconds). Any idea why that’s happening? Thanks!