Photon proper use

Options
I have just spent the whole day trying to get this to work and by the end of it, instead of feeling victory i feel a little despair as I'm sure that there is a better way of doing it...Here is what i was trying to do.

Two player's, the one who create the room is on the left the next appears to the right...Achieved like so( called from OnJoinedRoom() )
void SpawnPlayer()
{
	GameObject gObj = PhotonNetwork.Instantiate("Prefabs/"+playerPrefab.name, Vector3.up*5, Quaternion.identity, 0);

	playerRoll = gObj.GetComponent<WCNumberRoll>();
	thisPhotonView.RPC("firstPlayerSet",PhotonTargets.AllBufferedViaServer,gObj.GetPhotonView().viewID);
}

[RPC]
public void firstPlayerSet( int photonViewID )
{
	PhotonView pv = PhotonView.Find(photonViewID);

	pv.GetComponent<WCNumberRoll>().mm = this;
	pv.transform.parent = transform.parent;
	NGUITools.MarkParentAsChanged (pv.gameObject);

	pv.transform.localScale = new Vector3(1,1,1);
	pv.transform.localPosition = pointToSpawn.transform.localPosition;

	pointToSpawn = spawnPoint2;
}

So now the players both press a button to essentially roll some dice...getting the number to sync across both was very easy...However comparing the results and setting a label to announce the winner took a lot longer than i would have liked. here is the RPC call for when the button is pressed
[RPC]
	void Rolled(int photonViewID, int number)
	{
		PhotonView pv = PhotonView.Find(photonViewID);

		if(pv != null)
		{
			if(!pv.isMine)
			{
				opponentRoll = pv.GetComponent<WCNumberRoll>();
				opponentRoll.numberLabel.text = number.ToString();
			}
		}
	}

And the update function for checking who has gotten the greater roll.
void Update()
{
	CreateServerList();

	if(opponentRoll != null)
	{
		if(opponentRoll.hasRolled && playerRoll.hasRolled)
		{
			int opponentNum = int.Parse(opponentRoll.numberLabel.text);
			int playerNum = int.Parse(playerRoll.numberLabel.text);

			Debug.Log("opponent: "+opponentNum);
			Debug.Log("player: "+playerNum);

			string text = "Default";

			if(opponentNum < playerNum)
			{
				text = PhotonNetwork.player.name;
			}
			else
			{
				foreach(PhotonPlayer player in PhotonNetwork.playerList)
				{
					if( player.ID != PhotonNetwork.player.ID )
					{
						text = player.name;
					}
				}
			}

			showWinner.text = text + " wins";

			showWinner.gameObject.SetActive(true);
		}
	}
}

My main concern is that there is probably a much better and possibly easier way of doing it...It's also tremendously inflexible as code, I am also sure it does not gel well with the networking programming mind set one has to adopt and understanding while doing these things.

Any insight at all would be very appreciated thank you.

Comments

  • vadim
    Options
    Probably better approach is running all game logic on one client only, usually master client. It keeps game state, handles 'Roll' rpc's from both players and having all that data can easily compare numbers and update game state. After that this script will send rpc's to players with fresh data to update views.
  • Tobias
    Options
    I think it's kind of OK doing it this way. On the other hand, there's always lots of different ways.

    Another option is to use custom player properties with PhotonPlayer.SetCustomProperties(). Maybe also use a room Property as turn.
    Per turn, players roll and set 2 props: "v" (value) and "t" (turn). To access those Custom Properties, you could modify PhotonPlayer or just create an Extension for it, which tries to read the PhotonPlayer..customProperties Hashtable.

    You can also implement this callback (described in PhotonNetworkingMessage enum):
    void OnPhotonPlayerPropertiesChanged(object[] playerAndUpdatedProps) { }

    In any case: You need to know if both players did their roll for a turn.
    You can speed up things by calculating the result in the button click. Send it early, even before the local animation is finished. This gives both players something to look at while the other might send the result.
  • Thanks for the replies guys, Photon seems to be a great piece of kit so far, but the whole trial and error business although effective...is a tad slow, So other ways to use the API is most welcome.

    EDIT:
    Another question i have is about assigning references for photonviews you get off the server...How would you recommend doing it? To me it seems like the most ideal way of doing it would have an RPC in the start and send it's photon viewID to go find it in the scene to keep a reference of it.
  • Tobias
    Options
    I don't understand the new question, I think.
    There is no "off the server", unless you use the Server SDK and re-implement PUN for the server.
    It you need some PhotonView for general communication in the scene, you can simply place an empty object with a PhotonView in the scene. You can add a component on this scene GO that provides a reference as static field for easy access.
    You can also use RaiseEvent() in the latest PUN to send your own messages without any reference to an object.
  • Okay i'll try and be a bit more succinct with an example... Let's say each player needs to hold a a list of all other player's or rather certain components that each player has as a part of their game object or even scene. How would i go about filling that list for each player that either joins, or this component is added to the game later? Just so that each player in the game has access to each other thing in the game that isnt local or they do not own. I ask because in the code i got above shown here
    [RPC]
       void Rolled(int photonViewID, int number)
       {
          PhotonView pv = PhotonView.Find(photonViewID);
    
          if(pv != null)
          {
             if(!pv.isMine)
             {
                opponentRoll = pv.GetComponent<WCNumberRoll>();
                opponentRoll.numberLabel.text = number.ToString();
             }
          }
       }
    

    as you can see it assigns the opponentRoll from an RPC call, as later i need to do a check against myself versus the opponent i.e if(int.Parse(playerRoll.numberLabel.text)>int.Parse(opponentRoll.numberLabel.text)) and i need to hold a reference to do that or send another RPC to do the same again but that seems silly.

    This all works of course, and i do not mind assigning via RPC calls i am just curious as if there is another way to do this.
  • vadim
    Options
    RPC is powerful but not always appropriate tool for building photon apps. For many cases other synchronization methods which available in plugin are more optimal.
    Let's say each player needs to hold a a list of all other player's...
    When you mention players list, the first thing that comes to mind is PhotonNetwork.playerList with players custom properties. Tobias already wrote about it earlier. Did you try this approach?