Search code examples
c#unity-game-enginesynchronizationmultiplayer

Weapon is visible only to server host


Well i made a simple multiplayer shooting game and so far everything is working good except the chosen weapon is not showing for enyone but the host for example if i choose weapon 1 (ak47) nobody can see the object except the server host same goes for my other weapons and i belive i need to spawn them with NetworkServer.Spawn but i am not sure how to do it. Thank you for eny anwsers !!!

using UnityEngine;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

public class PlayerController : NetworkBehaviour
{
public Text Ammoleft;
[SyncVar]
public int Ak47Bullets = 30;

[SyncVar]
public int PipeShotgunBullets = 7;

[SyncVar]
public int currentWeapon;

public Transform[] weapons;

[SyncVar]
public string CurrentWeaponstr;

public GameObject ShottyBullet;
public GameObject Ak47Bullet;
public Transform bulletSpawn;
public float speed = 1; // speed in meters per second


void Update()
{

    if (!isLocalPlayer)
    {
        return;
    }

    float mouseInput = Input.GetAxis("Mouse X");
    Vector3 lookhere = new Vector3(0,mouseInput,0);
    transform.Rotate(lookhere);

    var x = Input.GetAxis("Horizontal") * Time.deltaTime * 3.0f;
    var z = Input.GetAxis("Vertical") * Time.deltaTime * 3.0f;

    transform.Translate(x, 0, 0);
    transform.Translate(0, 0, z);

    Vector3 moveDir = Vector3.zero;
    //moveDir.x = Input.GetAxis("Horizontal"); // get result of AD keys in X
    //moveDir.z = Input.GetAxis("Vertical"); // get result of WS keys in Z
    // move this object at frame rate independent speed:
    transform.position += moveDir * speed * Time.deltaTime;

    if (Input.GetKeyDown(KeyCode.Alpha1))
    {
        CmdSwitchtoAk();
    }
    if (Input.GetKeyDown(KeyCode.Alpha2))
    {
        CmdSwitchtoPipe();
    }

    if (Input.GetKeyDown (KeyCode.Mouse0) && CurrentWeaponstr == 
    "PipeShotgun" && PipeShotgunBullets > 0)
    {
        CmdFireShotty();
        PipeShotgunBullets -= 1;
        Ammoleft.text = "Left: " + PipeShotgunBullets;
        Debug.Log ("Shotpipe");
    }
    if (Input.GetKey (KeyCode.Mouse0) && CurrentWeaponstr == "Ak47" && 
    Ak47Bullets > 0) {
        CmdFireAk47();
        Ak47Bullets -= 1;
        Ammoleft.text = "Left: " + Ak47Bullets;
        Debug.Log ("ShotAk");
    }
}

[Command]
void CmdSwitchtoAk()
{
        changeWeapon(1);
        CurrentWeaponstr = "Ak47";

}

[Command]
void CmdSwitchtoPipe()
{
    changeWeapon(2);
    CurrentWeaponstr = "PipeShotgun";
}

// This [Command] code is called on the Client …
// … but it is run on the Server!
[Command]
void CmdFireAk47(){
    if (CurrentWeaponstr == "Ak47") {
        var Ak47bullet = (GameObject)Instantiate (
            Ak47Bullet,
            bulletSpawn.position,
            bulletSpawn.rotation);
        Ak47bullet.GetComponent<Rigidbody>().velocity = Ak47bullet.transform.forward * 6;
        NetworkServer.Spawn(Ak47bullet);
    }
}
[Command]
void CmdFireShotty()
{

    // Create the Bullet from the Bullet Prefab
    if (CurrentWeaponstr == "PipeShotgun") {
        var Pipebullet = (GameObject)Instantiate (
                         ShottyBullet,
                         bulletSpawn.position,
                         bulletSpawn.rotation);
        Pipebullet.GetComponent<Rigidbody>().velocity = Pipebullet.transform.forward * 6;
        NetworkServer.Spawn(Pipebullet);

    }

}

public override void OnStartLocalPlayer ()
{
    GetComponent<MeshRenderer>().material.color = Color.blue;
}

public void changeWeapon(int num) {

    currentWeapon = num;
    for(int i = 0; i < weapons.Length; i++) {
        if (i == num) {
            weapons [i].gameObject.SetActive (true);
        }
        else
            weapons[i].gameObject.SetActive(false);         
    }
    }
    }

here is the image:

enter image description here


Solution

  • You are calling a Command which is why it's only run on the server/host, commands is the server code, and RPC is the client code, so if you want to send some action to everyone you need to call RPC from Server/Host.

    public class PlayerController : NetworkBehaviour
    {
        [Command]
        void CmdSwitchtoAk()
        {
            RpcSwitchtoAk();
        }
    
        [ClientRpc]
        void RpcSwitchtoAk()
        {
            changeWeapon(1);
            CurrentWeaponstr = "Ak47";
        }
    }
    
    1. Call Command from Client
    2. The command run on the server, and then forward to all client using RPC
    3. the server call RPC
    4. All client get the callback

    Ref : Unity Unet Manual