Master Server And Lobby 主服务器和大厅
PUN always uses a master server and one or more game servers. The master server manages currently running games on the various game servers and will provide a game server address when you join or create a room. PUN (the client) automatically switches to that game server.
PUN总是使用一个主服务器和一个或多个游戏服务器。 主服务器管理当前运行游戏的各种游戏服务器和将提供一个游戏服务器地址当你加入或创建一个房间。 PUN(客户端),它会自动切换到游戏服务器。
Individual matches are known as Rooms. They are independent of each other and identified by name. Rooms are grouped into one or multiple lobbies. Lobbies are an optional part in matchmaking. If you don't use custom lobbies explicitly, PUN will use a single lobby for all rooms.
By default, PUN will join the default lobby after connecting. This lobby sends a list of existing rooms to the client, so the player can pick a room (by name or some properties listed). Access the current list by using PhotonNetwork.GetRoomList(). The lists is updated in intervals to keep traffic low.
Clients don't have to join a lobby to join or create rooms. If you don't want to show a list of rooms in your client, set PhotonNetwork.autoJoinLobby = false before you connect and your clients will skip the lobby.
You can use more than one lobby to organize room-lists as needed for your game. PhotonNetwork.JoinLobby is the method to join a specific lobby. You can make them up on the client side - the server will keep track of them. As long as name and type are the same, the TypedLobby will be the same for all clients, too.
A client is always just in one lobby and while being in a lobby, creating a room will relate to this lobby, too. Multiple lobbies mean the clients get shorter rooms lists, which is good. There is no limit to the rooms lists.
A parameter in JoinRoom, JoinRandomRoom and CreateRoom enables you to select a lobby without joining it.
Players won't notice each other in the Lobby and can't send data (to prevent issues when it's getting crowded).
The servers are all run on dedicated machines - there is no such thing as player-hosted ‘servers’. You don’t have to bother remembering about the server organization though, as the API all hides this for you.
The code above is required to make use of any PhotonNetwork features. It sets your client’s game version and uses the setup-wizard’s config (stored in: PhotonServerSettings). The wizard can also be used when you host Photon yourself. Alternatively, use Connect() and you can ignore the PhotonServerSettings file.
The loadbalancing logic for Photon uses your appID to separate your players from anyone else’s. The same is done by game version, which separates players with a new client from those with older clients. As we can’t guarantee that different Photon Unity Networking versions are compatible with each other, we add the PUN version to your game’s version before sending it (since PUN v1.7).
Creating and Joining Games 创建和加入游戏
Next, you’ll want to join or create a room. The following code showcases some required functions: 接下来,您将想要加入或创建一个房间。 下面的代码展示了一些需要的功能:
A list of currently running games is provided by the master server’s lobby. It can be joined like other rooms but only provides and updates the list of rooms. The PhotonNetwork plugin will automatically join the lobby after connecting. When you’re joining a room, the list will no longer update.
To display the list of rooms (in a lobby): 显示的房间列表
Alternatively, the game can use random matchmaking: It will try to join any room and fail if none has room for another player. In that case: Create a room without name and wait until other players join it randomly.
Advanced Matchmaking & Room Properties
Fully random matchmaking is not always something players enjoy. Sometimes you just want to play a certain map or just two versus two.
In Photon Cloud and Loadbalancing, you can set arbitrary room properties and filter for those in JoinRandom.
Room Properties and the Lobby
Room properties are synced to all players in the room and can be useful to keep track of the current map, round, starttime, etc. They are handled as Hashtable with string keys. Preferably short keys.
You can forward selected properties to the lobby, too. This makes them available for listing them and for random matchmaking, too. Not all room properties are interesting in the lobby, so you define the set of properties for the lobby on room creation.
Note that "ai" is not a key in the room-properties yet. It won't show up in the lobby until it's set in the game via Room.SetCustomProperties(). When you change the values for "map" or "ai", they will be updated in the lobby with a short delay, too.
请注意,“人工智能”还没有room-properties的关键。 它不会出现在大厅里,直到它设置在游戏中通过Room.SetCustomProperties()。 当你改变的值“地图”或“人工智能”,他们将在大堂与短的延迟更新,。
Keep the list short to make sure performance doesn't suffer from loading the list.
Filtering Room Properties in Join Random
In JoinRandom, you could pass a Hashtable with expected room properties and max player value. These work as filters when the server selects a "fitting" room for you.
If you pass more filter properties, chances are lower that a room matches them. Better limit the options.
Make sure you never filter for properties that are not known to the lobby (see above).
MonoBehaviour Callbacks 回调
PUN uses several callbacks to let your game know about state changes like “connected” or “joined a game”. All you have to do is implement the fitting method in any MonoBehaviour and it gets called when the event happens.
To get a good overview of available callbacks, take a look at the class Photon.PunBehaviour. If you make your script a PunBehaviour (instead of a MonoBehaviour), you can override individual callbacks easily. If you begin to type "override", your coding IDE should provide you a list of callbacks, so they are easy to find while coding, too.
This covers the basics of setting up game rooms. Next up is actual communication in games.
Sending messages in rooms 发送消息在房间
Inside a room you are able to send network messages to other connected players. Furthermore you are able to send buffered messages that will also be sent to players that connect in the future (for spawning your player for instance).
Sending messages can be done using two methods. Either RPCs or by using the PhotonView property OnSerializePhotonView. There is more network interaction though. You can listen for callbacks for certain network events (e.g. OnPhotonInstantiate, OnPhotonPlayerConnected) and you can trigger some of these events (PhotonNetwork.Instantiate). Don’t worry if you’re confused by the last paragraph, next up we’ll explain for each of these subjects.
Using Groups in PUN 用组
Groups are not synchronized when they are changed on any PhotonView. It's up to the developer to keep photonviews in the same groups on all clients, if that's needed. Using different group numbers for the same photonview on several clients will cause some inconsistent behaviour.组不同步时在任何PhotonView改变。 由开发人员保持photonviews在同一组对所有客户,如果这是必要的。 使用不同组数据相同的photonview几个客户会导致一些不一致的行为。
Some network messages are checked for their receiver group at the receiver side only, namely: 一些网络消息检查接收器组在接收机端,即:
- RPCS that are targeted to a single player (or MasterClient) rpc是针对一个单一的玩家(或MasterClient)
- RPCS that are buffered (AllBuffered/OthersBuffered). rpc缓冲(AllBuffered / OthersBuffered)。
- This includes PhotonNetwork.Instantiate (as it is buffered). 这包括PhotonNetwork。 实例化(缓冲)。
Technical reason for this: the photon server only supports interestgroups for messages that are not cached and are not targetted at sepcific actor(s). This might change in the future.
PhotonView is a script component that is used to send messages (RPCs and OnSerializePhotonView). You need to attach the PhotonView to your games gameobjects. Note that the PhotonView is very similar to Unity’s NetworkView.
At all times, you need at least one PhotonView in your game in order to send messages and optionally instantiate/allocate other PhotonViews.
To add a PhotonView to a gameobject, simply select a gameobject and use: “Components/Miscellaneous/Photon View”.
Observe Transform 观察变换
If you attach a Transform to a PhotonView’s Observe property, you can choose to sync Position, Rotation and Scale or a combination of those across the players. This can be a great help for prototyping or smaller games. Note: A change to any observed value will send out all observed values - not just the single value that’s changed. Also, updates are not smoothed or interpolated.
A PhotonView can be set to observe a MonoBehaviour. In this case, the script’s OnPhotonSerializeView method will be called. This method is called for writing an object’s state and for reading it, depending on whether the script is controlled by the local player.
一个MonoBehaviour PhotonView可以观察。 在这种情况下,脚本OnPhotonSerializeView方法将被调用。 调用此方法为写作对象的状态和阅读它,取决于该脚本是由当地的玩家。
The simple code below shows how to add character state synchronization with just a few lines of code more:
If you send something “ReliableDeltaCompressed”, make sure to always write data to the stream in the same order. If you write no data to the PhotonStream, the update is not sent. This can be useful in pauses. Now on, to yet another way to communicate: RPCs.
如果你发送一些“ReliableDeltaCompressed”,确保总是在相同的顺序向流写入数据。 如果你写PhotonStream没有数据,更新不发送。 这可能是有用的在停顿了一下。 现在,另一种方法来沟通:rpc。