Why does Photon work the way it does?

I don't get why Unity makes you write the code for the server in a client side script by saying "PhotonNetwork.whatever". I don't see why they can't just give you folder that's located on the server and you put all your game logic scripts in that folder rather than have every single client have a copy of the server side game logic code which inevitably comes with their download. Like why does the client have to say PhotonNetwork.Instantiate(...)? Can't the client instead just send their key strokes to the server, and the server decides whether to instantiate or not based on the code you would put the folder I had mentioned? The way that Photon does it seems to break the whole idea of a Client/Server system in that the server isn't really responsible for any of the game logic. I also don't get how something like collisions are calculated. Does a client only calculate the collisions for the player model that belongs to them and all other collisions are handled by their respective clients? If I'm missing something can someone please point it out?

Thanks

Comments

  • Hi @cekoivisto,

    hopefully I'm able to answer all of your questions satisfyingly, if not feel free to ask again.

    The way that Photon does it seems to break the whole idea of a Client/Server system in that the server isn't really responsible for any of the game logic.


    I guess this depends on whether you are talking about the Photon Cloud or the self-hosted Photon Server. When talking about the cloud you can say that it acts more like a mediator and handles message flow for example, making sure that sent messages by clients are delivered to the other clients and so forth. It also stores important messages for clients that join later on, Instantiation calls for example, telling new clients to instantiate certain objects. You are right, that the Cloud Servers don't process any custom game logic (besides Plugins used by Enterprise Customers, which is another topic).

    When talking about the self-hosted Photon Server instead it looks a little different because you can use custom game logic, either from injecting it through Plugins or creating your own server application. Besides that you still have all the basic functionality as you have by the using the Photon Cloud, but as told you can extend it.

    I also don't get how something like collisions are calculated. Does a client only calculate the collisions for the player model that belongs to them and all other collisions are handled by their respective clients?


    Basically yes, this is the way to handle it when using the Cloud. Again things can be different (but don't have to) when using the self-hosted Server with custom game logic where you can calculate collisions also on server-side.
  • Thanks for your response. So let's say that in my game if a player walks over a certain location an enemy will spawn, say using Photon.Instantiate(). Let's say player1 walks over that position and therefore calls Photon.Instantiate(). But since another player, say player2, has precisely the same game logic code as player1, wouldn't they also call Photon.Instantiate() when they see player1 walk over that location? Making for two new objects on both player1 and player2 screen instead of 1 in each? And in response to the last part in your comment, is there any point in a client storing the other clients' GameObjects in their script? Like would every client have a GameObject[] player variable that would store all players in the scene? My gut says no because that's redundant but I don't know any other way to access it. As far as I know Photon doesn't store a GameObject array on their server, where you could say PhotonNetwork.player[2] and it would return the GameObject. Also with your explanation wouldn't your game be highly prone to cheating because all game logic is done client side?

    Thanks
  • The PhotonNetwork.Instantiate call would normally either only be done by the Master Client, or you would execute the logic only if the player is the local player.

    In your example above, Only Player 1's client would instantiate as you would check "PhotonPlayer.IsLocal" before executing the logic.

    Accessing the local version of other player's GameObejcts is handy, for one thing, you may want to call an RPC on a remote player. So let's say Player1 had a power that let him kill other players on contact. You'd probably want to look for the collision with other players on Player 1's machine in this case, then if you detect he touched Player 2, you would call the Kill() RPC on the local version of Player 2 that you don't own. This RPC would then get sent over the network, and Player 2 would be killed on all the clients, including the client that owns Player 2.

    "PhotonPlayer.TagObject" is for storing a reference to an interesting script on your player object. This then lets you retrieve the GameObject for your player from "PhotonNetwork.playerlist" if you wanted.

    Cheating is somewhat of a concern, but this is where Photon Cloud Enterprise (and plugins) or running your own server would help. You could run code that would sanity check a player's movement for instance to make sure they haven't hacked their speed variable. You could also run code that makes sure they haven't earned too much gold in a given time period.

    Our current approach is not to worry about cheating yet, just concentrate on getting the game running well in Photon Cloud. Then, if we're lucky enough for it to be popular and people start trying to cheat it, we will migrate to Photon Cloud or our own servers. This should be pretty painless as most of the client code will remain the same.

    Hope this helps!
  • Hi @cekoivisto and @nindim,

    just some more input about this: Instead of checking the PhotonPlayer.IsLocal condition (I guess this is true on each client) I would prefer using the photonView.isMine condition before doing anything network related (RPC calls, RaiseEvent...).

    Cheating in multiplayer games is a big problem in general and can't be prevented as far as I would say. If you run your game through the Cloud, things might get even more worse. The only approach here seems to 'trust' the MasterClient and let him check important operations before executing those. This however would result in more computation time on this client and might affect performance in worst case.

    When running your game on self-hosted servers (or with plugins) you can go against some cheating (speed hacking e.g.), but you wouldn't eliminate all cheats people can think about. For example clients still can decrypt received packages and read position data of other clients out to gain an illegal advantage, just to name one thing.

    Our current approach is not to worry about cheating yet, just concentrate on getting the game running well in Photon Cloud. Then, if we're lucky enough for it to be popular and people start trying to cheat it, we will migrate to Photon Cloud or our own servers.


    Sounds like a good idea so far.