Consistently loop through players in a room

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.

Consistently loop through players in a room

MomasVII
2020-12-15 21:11:03

I'm really struggling to find how I can, in an RPC, loop through every player in a consistent order. Preferable GetPlayerNumber.

Here is what I am trying to do...

[PunRPC]  
    public void RPC_SetPlayers() {  
      GameObject[] playersArray = GameObject.FindGameObjectsWithTag("Player");  
      foreach(GameObject plr in playersArray) {  
          plr.GetComponent<PointToPointRace>().playersToPositions = true;  
      }  
    }

Simple stuff, but, each player that runs this RPC will have a different playersArray order. Or at least that's what seems to be happening here.

How can I say, "Get every player in the room and loop through them as gameobjects".
I can see playerList but that returns a player class that can't access the scripts attached to my player right?
Unless I do some convoluted like PhotonView.Find(player.ID) or something right?

I don't know I just want the most logical solution cause my mobile game is getting bogged down and if I don't stomp this out early it will lag.

Thanks

Comments

LeeroiJenkiins
2020-12-15 21:40:01

whats happening here is that every client gets that RPC call and then every client also runs through that foreach loop you have.. and theyre ALL setting them.
you need to make it so just the master client sets it or they all set it individually through customProperties that the master checks for OnPlayerPropertiesUpdate.

also, im not sure how you're calling that RPC, but it may be being called multiple times..
If you must achieve this through an RPC though, a simple way to make sure it's only run once is to add:

[PunRPC]  
    public void RPC_SetPlayers() {  
     if(!PhotonNetwork.IsMasterClient) return;

      GameObject[] playersArray = GameObject.FindGameObjectsWithTag("Player");  
      foreach(GameObject plr in playersArray) {  
          plr.GetComponent<PointToPointRace>().playersToPositions = true;  
      }  
    }

MomasVII
2020-12-16 19:46:04

I have actually pre RPC called managed who is calling it which is basically what your if statements says there so it is only being run by one player.
Here is what I'm trying to do.

It's a racing game so...
When a player collects a Race object I want to say "Hey all players, here is the predetermined position you will spawn in for the race, i.e. their poll position. Every player is getting poll poisition 0 and it just stacks all the cars on top of each other.
So I think when they run playerArray they are returning themselves in position 0 and the other playyer in position 1.
So player 1's array is like
[0] Me
[1] Player 2
and Player 2 is
[0] Me
[1] Player 1
So i think i need a consistent list of players that each player can read from. Or maybe you have another suggestion?
Thanks

public void RPC_SetPlayers() {  
      GameObject[] playersArray = GameObject.FindGameObjectsWithTag("Player");  
      int x = 0;  
      foreach(GameObject plr in playersArray) {  
          plr.GetComponent<PointToPointRace>().pollPosition = x++;  
          plr.GetComponent<PointToPointRace>().playersToPositions = true;  
      
      }  
    }

LeeroiJenkiins
2020-12-16 20:26:08

The difference between checking for master when making the RPC call and within the RPC call is:

  1. Check if is master before RPC:
  • only the master calls for it to execute, but all clients still run and process everything in the RPC
  1. Check if is master in RPC:
  • only the master will actually run this RPC in the call, no other client will

It sounds like you issue is you're only using #1, and since its a racing game, you probably don't want to use #1 as all clients can pickup this object, and not just the master. But you also only want the call to happen once, and the way to ensure that is #2.

So remove your check for if(PhotonNetwork.IsMasterClient) before calling the RPC and only have that check within the RPC

Depending on how many of each of these pick up items are in your game / race. You can also achieve this with customProperties and simply in your gameManager check for OnPlayerPropertiesUpdate. This route has more limitations, but nothing a good algorithm couldn't solve.

Back to top