Rockets in fast games - which of the two options?

Options
Hello, I am creating a fast racing game with Multiplayer. The players are able to shoot weapons, for example a Rocket. Rockets travel with triple the speed down the track.

I am currently facing issues in how to spawn Rockets. Before, I made a NetworkRocket prefab with a PhotonView and sync pos+rot. But when a participant triggers his Rockets, it takes a while for the Master to Network.Instantiate them so the participant moved already and the Rockets will spawn behind him, hitting the triggerer xd

I came with two ideas but am not sure what is best:

Idea 1
Spawn the "offline" prefab of the Rocket locally at the triggerer. This way his Rockets direction will always perfectly align with the rotation his car is facing. At the same time, send an RPC with position and rotation to spawn a NetworkRocket for all other clients. Let this NetworkRocket have a trigger and just destroy it on impact. When the local Rocket of the triggerer hits another car, sync health [already done].
This means that the Rocket hit logic always remains to the triggerer, no matter if he is the master or not.

Idea 2
After hitting the shoot button, send an RPC to the master to trigger a NetworkRocket. Same behaviour of the NetworkRocket as above except for the triggerer: He will instantiate an offline Rocket and hit logic also remains at the triggerer.
The difference between idea 1 is that the local Rocket will be spawned by the RPC in Idea 2 for all players and in Idea 1 it will be spawned right away for the triggerer and with the RPC for all others. In both cases, the Rocket position and rotation is not synced across the network, every Rocket path is calculated locally.

I have to mention that the Rocket can bounce, so I can't give only start position and rotation and apply a force and that's it for movement.

What would be the best approach? My very first approch to make all Rockets [inlcuding hit logic] with a NetworkRocket prefab was not successful, or maybe this was indeed the best approach and I just did mistakes in the code?

Let me know if you need more details and thx for every help!

EDIT: Currently I am using PUN. Would using Bolt improve the situation?

Comments

  • If you can accomplish it with an RPC, that would definitely be best for performance. It sounds like the issue you were having with it hitting itself was the instantiation data being sent to the RPC.
    you can't create it the same way as a regular unity object, it'll have to be done like:
    [PunRPC]
        public void ShootRocket(Vector3 spawnPos, Quaternion spawnRotation)
        {
            GameObject projectile = Instantiate(player_Projectile, spawnPos, spawnRotation);
            //can set the Player owner here / add force, etc.
            projectile.GetComponent<PlayerProjectile_Multiplayer>().AddForce();
        }
    

    The key is to create the spawn info and then send the spawn info the the RPC when you call it:
    Vector3 enemyLookPos_v = currentEnemy.transform.position - transform.position;
            enemyLookPos_v.y = 0;
            Quaternion enemyLookPos = Quaternion.LookRotation(enemyLookPos_v);
            Vector3 spawnPos = currentEnemy.transform.position;
            photonView.RPC("SpawnArrows", RpcTarget.AllViaServer, spawnPos, enemyLookPos);
    

    If that doesn't work, then you'll want to add a PhotonView and Photon Transform View (or RidigidBody if you're using physics) component.

    make sure the PhotonView synchronization is: "Unreliable"
    on your rocket script make sure the class extends IPunObservable

    and add:
    public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
        {
            if (stream.IsWriting)
            {
                // We own this player: send the others our data
                stream.SendNext(this.rocketSpeed);
            }
            else
            {
                // Network player, receive data
                this.rocketSpeed = (float)stream.ReceiveNext();
            }
        }
    
    this is just a template, you'll need to send its speed value though so it can account for lag compensation