Am I misunderstanding sending an RPC to a player?

The whole answer can be found below.

Please note: The Photon forum is closed permanently. After many dedicated years of service we have made the decision to retire our forum and switch to read-only: we've saved the best to last! And we offer you support through these channels:

Try Our
Documentation

Please check if you can find an answer in our extensive documentation on PUN.

Join Us
on Discord

Meet and talk to our staff and the entire Photon-Community via Discord.

Read More on
Stack Overflow

Find more information on Stack Overflow (for Circle members only).

Write Us
an E-Mail

Feel free to send your question directly to our developers.

Am I misunderstanding sending an RPC to a player?

jeffries7
2020-12-11 14:55:54

So I thought I had a pretty good grasp on using Photon as I'm pretty deep into a project. However, I'm having an issue calling an RPC on multiple clients that have been sent from another client.

The concept is Player 1 clicks a local UI button that is meant to tell Player 2, Player 3, etc to do something locally (conditionally based on some custom properties).

public void ForceOpenMap()  
{  
        foreach (KeyValuePair<int, Player> playerInfo in PhotonNetwork.CurrentRoom.Players)  
        {  
            object hasMap;

            if (playerInfo.Value.CustomProperties.TryGetValue(CharacterAttributes.HasMap, out hasMap))  
            {  
                if ((bool)hasMap== true)  
                {  
                    photonView.RPC("openMap", playerInfo.Value);  
                }  
            }  
        }  
}

[PunRPC]  
private void openMap()  
{  
      SetMainCanvasVisibility(true);          
}  

This doesn't open the map locally on the other clients but it will open the map on the remote version of the client that sent the RPC. This would make sense as the client that sent the RPC is listed in the CurrentRoom.Players...however it doesn't open the map locally, it opens it for that client remotely on all the other clients. This makes me believe I'm doing something fundamentally wrong.

I read here that RPC calls are only sent between the same PhotonView within the room/lobby. If this is the case then why are you able to specify specific players when targeting an RPC?

This is the first time I'm trying to do something like this with Photon and I'm just a little confused as to why it doesn't work.
Am I going about this in the completely wrong way?

Also, I'm not actually using this to open a map but I've changed the names to make the example easier to understand.

Comments

jeffries7
2020-12-11 14:59:27

I'm now starting to think that specifying a certain player just means that the RPC is called on the PhotonView associated with the player that made the RPC but on the client of the player specified.

LeeroiJenkiins
2020-12-15 01:56:24

Im a little confused as to what you're trying to accomplish here as the outcome you don't want looks like what you're asking for in your code there.

If you want the client that clicked the button to do one thing but the others to do different add:

[PunRPC]  
private void openMap()  
{  
      if(photonView.IsMine)  
      SetMainCanvasVisibility(true);  
      else  
      //whatever every other client should do.  
}

if its specifically the master that is making the call and the other clients needing its info, instead of photonView.IsMine, use PhotonNetwork.IsMasterClient

jeffries7
2020-12-15 14:04:47

I don't want the client that clicked the button to do anything. I want the action to occur for the other players on their local clients.
I think I was misunderstanding what specifying a player meant within an RPC call.

Player 1 presses a button which triggers an action (in this case, UI to open) to happen to player 2.

LeeroiJenkiins
2020-12-15 16:42:05

ah i see what you mean. Did you get it working?
should be something like:

public void ForceOpenMap()  
{  
        if (!photonView.IsMine) return;

        foreach (KeyValuePair<int, Player> playerInfo in PhotonNetwork.CurrentRoom.Players)  
        {  
            object hasMap;

            if (playerInfo.Value.CustomProperties.TryGetValue(CharacterAttributes.HasMap, out hasMap))  
            {  
                if ((bool)hasMap== true)  
                {  
                    photonView.RPC("openMap", RpcTarget.Others);  
                }  
            }  
        }  
}

[PunRPC]  
private void openMap()  
{  
      SetMainCanvasVisibility(true);          
}

jeffries7
2021-01-04 12:02:12

@LeeroiJenkiins wrote: »

ah i see what you mean. Did you get it working?
should be something like:

public void ForceOpenMap()
{
if (!photonView.IsMine) return;

       foreach (KeyValuePair<int, Player> playerInfo in PhotonNetwork.CurrentRoom.Players)  
       {  
           object hasMap;

           if (playerInfo.Value.CustomProperties.TryGetValue(CharacterAttributes.HasMap, out hasMap))  
           {  
               if ((bool)hasMap== true)  
               {  
                   photonView.RPC("openMap", RpcTarget.Others);  
               }  
           }  
       }  

}

[PunRPC]
private void openMap()
{
SetMainCanvasVisibility(true);
}

Late reply as I was away from this project over Christmas.

I can confirm that the code above does not work.

I believe an RPC is only executed on the other instances of that gameobject on other users clients.

So an RPC on client 1 is only called on the other versions of client 1.
I'd need to cycle through all of the clients within the scene and call the RPC accordingly, at least that is how I'm understanding it.

Tobias
2021-01-07 16:19:29

An RPC targets a specific object, yes. All clients should know this object and have a script that matches the RPC name string.

You can call it with RpcTarget.All and the local client will execute the RPC as well.

jeffries7
2021-01-19 10:00:49

Coming back to this in case anyone else was understanding this incorrectly as I was, which was also my fault completely. After taking some time and stepping back it all makes sense now.

public void ForceOpenMap()  
{  
        PhotonView[] photonViews = FindObjectsOfType<PhotonView>();

        for (int i = 0; i < photonViews.Length; i++)  
        {  
            if (photonViews[i].gameObject.tag == "Player")  
            {  
                if (photonViews[i].Owner != photonView.Owner)  
                {  
                    if ((bool)photonViews[i].Owner.CustomProperties[CharacterAttributes.HasMap] == true)  
                    {  
                        photonViews[i].RPC("openMap", RpcTarget.All);  
                    }  
                }  
            }  
        }  
}

[PunRPC]  
private void openMap()  
{  
      SetMainCanvasVisibility(true);          
}  

This is just example code, typically you might already have references to all current players photon views. If not then this would work. Checking against a tag as there are be other objects in the scene other than the player with a photon view(you'd probably want a better system than this anyway).

Back to top