Search Unity

Third Party PhotonNetwork.Instantiate() vs RPC calls

Discussion in 'Multiplayer' started by Ebonicus, Jan 17, 2020.

  1. Ebonicus

    Ebonicus

    Joined:
    Oct 31, 2016
    Posts:
    158
    Hello,

    Everywhere I have researched states PhotonNetwork.Instantiate() should only be used for major player controlled items such as avatars, and that bullets and attacks, etc. should be made using RPC calls for efficiency.

    I tested both ways, and for some reason the RPC method is much slower performance wise, and has lag and framerate impacts for high speed projectile creation, such as machine guns.

    Below are the two pieces of code I tested for firing bullets.

    RPC Method Call:
    Code (CSharp):
    1.  
    2. [PunRPC]
    3. void FireBulletViaRPC(int ownerPVID, Vector3 bulletLoc, Quaternion bulletRotation, Vector3 ownerVelocity) {
    4.  
    5.             //Right way, inside an RPC call
    6.  
    7.             GameObject tmp = Instantiate (bulletPrefab, bulletLoc, bulletRotation);
    8.  
    9.             //We need to add our velocity to bullet so we dont fly past it at full speed.
    10.  
    11.             //Connect with bullet first to tel it about creator
    12.             MultiplayerRPCBullet tmpBlt = tmp.GetComponent<MultiplayerRPCBullet> ();
    13.             tmpBlt.ownerPVID = ownerPVID; //who's yur daddy
    14.             tmpBlt.myOwnerVelocity = ownerVelocity; //start at his speed
    15.  
    16.  
    17.  
    18.  }
    19.  
    And I compare that to my original code:

    Code (CSharp):
    1.  
    2. void FireBulletViaInstantiate(int ownerPVID, Vector3 bulletLoc, Quaternion bulletRotation, Vector3 ownerVelocity) {
    3.  
    4.  
    5.             GameObject tmp = PhotonNetwork.Instantiate (pathToBullet, bulletLoc, bulletRotation, 0);
    6.  
    7.             //We need to add our velocity to bullet so we dont fly past it at full speed.
    8.  
    9.             //Connect with bullet first to tel it about creator
    10.             MultiplayerRPCBullet tmpBlt = tmp.GetComponent<MultiplayerRPCBullet> ();
    11.             tmpBlt.ownerPVID = ownerPVID; //who's yur daddy
    12.             tmpBlt.myOwnerVelocity = ownerVelocity; // start at his speed
    13.  
    14.  
    15.  
    16. }
    17.  
    For both methods they are simply called with mouse0 down event handler with a cooldown, and encapuslated with PV.ismine properly. Since that code is shared by both tests, I felt it is not relevant to share it.

    There is significant performance increase of after effects, such as bullet impacts etc. showing up much more reliably using RPC method calls. With this method all projectiles fired are visible, never lost, and always produce their destruction effects, but collision with players is very unreliable.

    However, using the network instatiate produces much better collision detection, at the cost of having more complications when deleting a network instantiate projectile with a PV component.

    I have seen other people new to network programming state they used PhotonNetwork.Instantiate() within the RPC method. That makes no sense to me, as you would be broadcasting a messgae to all players, and they in turn would broadcast a room-wide instantiation, causing a cascade of more projectiles than necessary, is that incorrect?

    I though the whole purpose of using RPC method, was each machine would just locally create their own projectiles, which have no PhotonView component and just operate locally.

    If anyone can clarify what I am doing wrong, it would be appreciated, thanks.
     
  2. drawcode

    drawcode

    Joined:
    Jul 21, 2008
    Posts:
    72
    If you are Instantiating at runtime without an ObjectPool there will be lag. Any instantiation at runtime will create lag and cause the garbage collector to trigger here and there without some sort of pooler.

    Search for an object pooler in Unity and preload a decent amount of bullets for your game and it should speed up that part. The RPC call will still have some lag on the network a bit and bullets are probably best done with rays/timed or simulated but you should at least get a faster repeated call.

    There is a PUN ObjectPool see here in the 'Using The PrefabPool' section: https://doc.photonengine.com/en-us/pun/current/gameplay/instantiation
    https://doc-api.photonengine.com/en/pun/v2/class_photon_1_1_pun_1_1_default_pool.html

    Or make your own
    https://forum.unity.com/threads/stop-wasting-memory-recycle-your-objects.34582/ (best one)

    Uses these two files:
    https://github.com/shaunvxc/icy-alps/blob/master/core/ObjectPoolManager.cs
    https://github.com/shaunvxc/icy-alps/blob/master/core/ObjectPool.cs

    Or
    https://github.com/prime31/RecyclerKit
    https://github.com/Rfrixy/Generic-Unity-Object-Pooler/blob/master/ObjectPooler.cs


    More info on the problem, runtime instantiation
    https://learn.unity.com/tutorial/object-pooling

    The Photon Asteroids sample will probably help on the shooting part: https://doc.photonengine.com/en-us/pun/current/demos-and-tutorials/package-demos/asteroidsdemo

    There is a big about solving synchronization issues by adding lag compensation.

    As far as your second point about spawning on their own and controlling it, yes that is correct. When you spawn using an RPC it will create on all players connected screens but not be networked any longer, it will have to match speed/direction/time etc and if it hits something that is a PhotonView the collision will also have to be RPC'd to all if it hits or when the player health runs out, major events. Ultimately you want the RPC to only go when they are in the same area or space otherwise it is not necessary. Fast real-time games use a server simulation or rays/time to make it faster but for small amounts of players RPCs are ok.
     
    Last edited: Jan 19, 2020
    mpistella likes this.