[Command] -related problem: Objects don't instantiate on other clients.

Hello.

We are making a ship battle game that’s played over the internet. The first player creates a server that other players can join into. Right now the ships spawn correctly and they move on all clients, but cannon shots only show on the player’s own client. The cannon shots are instantiated objects that have velocity set in relation to the ship it’s fired from. The cannonballs have their own Network Identity with Local Player Authority unchecked. They also have Network Transform with Sync Rigidbody 3D. Cannonball prefab is also registered as spawnable prefab.

Can you help us understand what’s wrong with our code? Is [Command] a good way to make this happen?

The following code is linked to the player that instantiates the object:

    void FixedUpdate () {

        if (!_identity.isLocalPlayer)
            return;

        if (Input.GetKey(KeyCode.Q) && Time.time > _nextFire)
        {
            _nextFire = Time.time + _fireRate;
            CmdDoFireV(_missileLifetime);
        }

        if (Input.GetKey(KeyCode.E) && Time.time > _nextFire2)
        {
            _nextFire2 = Time.time + _fireRate2;
            CmdDoFireO(_missileLifetime);
       
        }


    }



    private GameObject missile;
    private GameObject missile1;
    private GameObject missile2;
    private GameObject missile3;
    private GameObject missile4;
    private GameObject missile5;
    private GameObject missile6;
    private GameObject missile7;

   [Command]
    void CmdDoFireV(float lifeTime)
    {

        missile = (GameObject)Instantiate(_missilePrefab, _missileSpawnPoint.position, Quaternion.identity);
    
        missile1 = (GameObject)Instantiate(_missilePrefab, _missileSpawnPoint1.position, Quaternion.identity);

        missile2 = (GameObject)Instantiate(_missilePrefab, _missileSpawnPoint2.position, Quaternion.identity);
   
        missile3 = (GameObject)Instantiate(_missilePrefab, _missileSpawnPoint3.position, Quaternion.identity);

        Rigidbody rigid = missile.GetComponent<Rigidbody>();
        rigid.velocity = ship.GetComponent<Rigidbody>().velocity + (transform.right * -_missileSpeed);
        Destroy(missile, lifeTime);

        Rigidbody rigid1 = missile1.GetComponent<Rigidbody>();
        rigid1.velocity = ship.GetComponent<Rigidbody>().velocity + (transform.right * -_missileSpeed);
        Destroy(missile1, lifeTime);

        Rigidbody rigid2 = missile2.GetComponent<Rigidbody>();
        rigid2.velocity = ship.GetComponent<Rigidbody>().velocity + (transform.right * -_missileSpeed);
        Destroy(missile2, lifeTime);

        Rigidbody rigid3 = missile3.GetComponent<Rigidbody>();
        rigid3.velocity = ship.GetComponent<Rigidbody>().velocity + (transform.right * -_missileSpeed);
        Destroy(missile3, lifeTime);

        NetworkServer.Spawn(missile);
        NetworkServer.Spawn(missile1);
        NetworkServer.Spawn(missile2);
        NetworkServer.Spawn(missile3);
    }

     
  [Command]
    void CmdDoFireO(float lifeTime)
    {

        missile4 = (GameObject)Instantiate(_missilePrefab, _missileSpawnPoint4.position, Quaternion.identity);

        missile5 = (GameObject)Instantiate(_missilePrefab, _missileSpawnPoint5.position, Quaternion.identity);

        missile6 = (GameObject)Instantiate(_missilePrefab, _missileSpawnPoint6.position, Quaternion.identity);

        missile7 = (GameObject)Instantiate(_missilePrefab, _missileSpawnPoint7.position, Quaternion.identity);

        Rigidbody rigid = missile4.GetComponent<Rigidbody>();
        rigid.velocity = ship.GetComponent<Rigidbody>().velocity + (transform.right * _missileSpeed);
        Destroy(missile4, lifeTime);

        Rigidbody rigid1 = missile5.GetComponent<Rigidbody>();
        rigid1.velocity = ship.GetComponent<Rigidbody>().velocity + (transform.right * _missileSpeed);
        Destroy(missile5, lifeTime);

        Rigidbody rigid2 = missile6.GetComponent<Rigidbody>();
        rigid2.velocity = ship.GetComponent<Rigidbody>().velocity + (transform.right * _missileSpeed);
        Destroy(missile6, lifeTime);

        Rigidbody rigid3 = missile7.GetComponent<Rigidbody>();
        rigid3.velocity = ship.GetComponent<Rigidbody>().velocity + (transform.right * _missileSpeed);
        Destroy(missile7, lifeTime);

        NetworkServer.Spawn(missile4);
        NetworkServer.Spawn(missile5);
        NetworkServer.Spawn(missile6);
        NetworkServer.Spawn(missile7);
    }

Firstly, you’re re-writing too much code. You need to wrap your spawn process in a function of itself, like this:

public void MissileFire(Vector3 _spawnPosition)
{
        GameObject missile = (GameObject)Instantiate(_missilePrefab, _spawnPosition, Quaternion.identity);

        missile.GetComponent<Rigidbody>().velocity = ship.GetComponent<Rigidbody>().velocity + (transform.right * _missleSpeed);
       Destroy(missile, lifeTime);
}

Then, inside your Command(s) just call the function.

[Command]
public void CmdMissileFireV()
{
        MissileFire(missleSpawnPoint1.position);
        MissileFire(missleSpawnPoint2.position);
        MissileFire(missleSpawnPoint3.position);
        MissileFire(missleSpawnPoint4.position);
}
[Command]
public void CmdMissileFireO()
{
        MissileFire(missleSpawnPoint5.position);
        MissileFire(missleSpawnPoint6.position);
        MissileFire(missleSpawnPoint7.position);
        MissileFire(missleSpawnPoint8.position);
}
  1. Now to your problem. Does this work for the client or just for the server? If player A starts the game, and player B joins the game…and player B tries to fire missiles, does it work on player B’s computer?

The idea is that my ship has 4 cannons both sides of ship. Then if Q is clicked it shoots left side cannons and E opposite side. Every cannon has it’s own spawn point where cannonballs (missiles in my code) are spawned. Is that possible to make happen with wrapping the code like that?
In my code (at first post) it didn’t matter if user was Client or Server, both worked only in its own screen but instantiated them well there. So network didn’t success there.

I tried to replace [command] to [client]. In that case missiles what i shot from B (client) screen, seem on server screen (A).
But that case didn’t work another way. Server (A) shots seem only its own screen and client (B) didn’t see them.

Did that clarify the situation any better?
And thanks for the reply!

To your question, yes it will work. I simply simplified your code. Where you had written almost 70 lines of code, I did the same thing in 23 lines.

Back to the issue. I can’t see what might be causing the issue.

Thank you for taking the time to look at our problem and helping us clean our code. We managed to solve the problem with a few small changes.

   public void MissileFireV(Vector3 _spawnPosition)
    {
        GameObject missile = (GameObject)Instantiate(_missilePrefab, _spawnPosition, Quaternion.identity);

        missile.GetComponent<Rigidbody>().velocity = ship.GetComponent<Rigidbody>().velocity + (transform.right * -_missileSpeed);
        NetworkServer.Spawn(missile);
        Destroy(missile, 2.5f);
    }
    public void MissileFireO(Vector3 _spawnPosition)
    {
        GameObject missile = (GameObject)Instantiate(_missilePrefab2, _spawnPosition, Quaternion.identity);

        missile.GetComponent<Rigidbody>().velocity = ship.GetComponent<Rigidbody>().velocity + (transform.right * _missileSpeed);
        NetworkServer.Spawn(missile);
        Destroy(missile, 2.5f);
    }


    [Command]
    public void CmdMissileFireV()
    {
        MissileFireV(_missileSpawnPoint1.position);
        MissileFireV(_missileSpawnPoint2.position);
        MissileFireV(_missileSpawnPoint3.position);
        MissileFireV(_missileSpawnPoint4.position);
    }
    [Command]
    public void CmdMissileFireO()
    {
        MissileFireO(_missileSpawnPoint5.position);
        MissileFireO(_missileSpawnPoint6.position);
        MissileFireO(_missileSpawnPoint7.position);
        MissileFireO(_missileSpawnPoint8.position);
    }

Adding “NetworkServer.Spawn(missile);” was the thing that made the difference.

That’s weird, because you already had NetworkServer.Spawn() in your original code.