Am I misunderstanding sending an RPC to a player?

Options
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
    Options
    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
    edited December 2020
    Options
    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
    Options
    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.
  • 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
    Options
    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
    Options
    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
    Options
    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).