Search code examples
c#unity-game-engineunity3d-unet

Why do I need [Command] for NetworkServer.Spawn() , but not for NetworkServer.Destroy()?


I have this script from a multiplayer shooter that I'm making , and I have a question about the use of the [Command] attribute

This is the code:

[Command]
public void CmdShoot()
{
    //Creat the bullet
    GameObject Bullet = (GameObject)Instantiate(bulletPrefab, Barrle.transform.position, Barrle.transform.rotation);
    BulletController bc = Bullet.GetComponent<BulletController>();
    bc.SetOrigin(this.transform.name);
    NetworkServer.Spawn(Bullet);

    //Shoot the bullet
    Rigidbody rb = Bullet.GetComponent<Rigidbody>();
    rb.AddForce(cam.transform.forward * BulletForce, ForceMode.VelocityChange);
}


//Called from the bullet when it hit something
[Command]
public void CmdHit(GameObject other,GameObject _bullet)
{
    Debug.Log(other.transform.name);
    GameObject bullet = _bullet;
    if (other.GetComponent<NetworkIdentity>() != null)
    {
        //Destroy the coin if you hit it
        if (other.transform.name.Equals("Coin"))
        {
            NetworkServer.Destroy(other.gameObject);
        }

        //Apply dmg to other player if hit it
        else if (other.transform.tag.Equals("Player"))
        {
            Player playerHit = GameManager.GetPlayer(other.transform.name);
            playerHit.TakeDamage(BulletForce);
        }
    }

    //Destroy the bullet if you hit anything
    NetworkServer.Destroy(bullet.gameObject);  
}

Now if I remove the [Command] attribute from CmdShoot , the remote player isn't able to shoot , because he has no NetworkServer (as far as I understand)

I would assume it would be the same thing for CmdHit , and the remote player wont be able to destroy the bullet or the coin , because he does not have a NetworkServer.

But.. CmdHit works fine even without the [Command] attribute, and Im wondering why?


Solution

  • If you check out Unity's documentation about remote actions that should help you out here. When you add the [Command] attribute to a method you mark that method as code to be executed on the server once the client calls it.

    In your case this means that as soon as there is input on the client which results in a shoot (pressing Space for example) you call CmdShoot() yourself, which then will be executed on the server. This is an event that needs to be sent to the server, otherwise the remote player won't ever have that bullet. CmdHit however is a local action that doesn't have to be executed on the server - as you wrote in your own code comment, CmdHit will be called from the bullet as soon as it hits something. Given that the bullet exists on both clients, it will hit something on both clients, so that information doesn't have to be sent over on the network.