其中用到了 Photon Cloud,内有很多运行 Photon Server 的机子。 Client 先连接到 Name Server,然后检查 AppId,知道要去哪个 region,然后去对应的 Master Server Master Server 是管理区域服务器的 hub,它让 Client 去到某个 Game Server
只有相同 AppId 的玩家可以相互看到对方 还有 Game Version 字符串,阻隔旧版本与更新版本的玩家
Region 是一个个有序分开的区域,在全球范围内分布,为了玩家之间更好的连接 不同区域之间相互分离
Room : Photon Cloud 是以房间为基础的游戏,每个配对只有优先的玩家(16人上限) 房间内的每个人接受其他人发送的任何公有信息 在两个房间内的玩家无法交流 最好的进入房间的方法是使用 Random Matchmaking,询问 server 任意一个房间,或指明一些玩家希望的额外属性 每个房间都有一个名字,也叫标识符 identifier,除非房间满了或关闭了,都可以通过名字加入房间 Master Server 可以提供房间的列表
Lobby:在 Master Server 上,列出游戏中的所有房间,但是玩家之间不能相互交流
连接到 Server
点击 Window -> Photon Unity Networking -> Highlight Server Settings 点开下面的 asset 文件,右侧 PUN Logging 选择 Full
新建一个 Launcher 脚本,如下
注意头文件为 using Photon.Pun 注意可能会有重名脚本,可以自行添加命名空间等方法
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
public class Launcher : MonoBehaviour
{
private string gameVersion ="1";voidAwake(){// Then let master server can use PhotonNetwork.LoadLevel()// Everyone will see the same level
PhotonNetwork.AutomaticallySyncScene = true;}voidStart(){Connect();}
public voidConnect(){if(PhotonNetwork.IsConnected){
PhotonNetwork.JoinRandomRoom();}else{
PhotonNetwork.ConnectUsingSettings();
PhotonNetwork.GameVersion = gameVersion;}}}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Photon.Pun;
using Photon.Realtime;
public class Launcher : MonoBehaviourPunCallbacks
{
private string gameVersion ="1";[SerializeField]
private byte maxPlayersPerRoom =4;[SerializeField]
private GameObject controlPanel;[SerializeField]
private GameObject progressLabel;voidAwake(){// Then let master server can use PhotonNetwork.LoadLevel()// Everyone will see the same level
PhotonNetwork.AutomaticallySyncScene = true;
progressLabel.SetActive(false);
controlPanel.SetActive(true);}
public voidConnect(){
progressLabel.SetActive(true);
controlPanel.SetActive(false);if(PhotonNetwork.IsConnected){
PhotonNetwork.JoinRandomRoom();}else{
PhotonNetwork.ConnectUsingSettings();
PhotonNetwork.GameVersion = gameVersion;}}
public override voidOnJoinRandomFailed(short returnCode, string message){
Debug.Log("PUN Basics Tutorial/Launcher:OnJoinRandomFailed() was called by PUN. No random room available, so we create one.\nCalling: PhotonNetwork.CreateRoom");// #Critical: we failed to join a random room, maybe none exists or they are all full. No worries, we create a new room.
PhotonNetwork.CreateRoom(null, new RoomOptions { MaxPlayers = maxPlayersPerRoom });}
public override voidOnJoinedRoom(){
Debug.Log("PUN Basics Tutorial/Launcher: OnJoinedRoom() called by PUN. Now this client is in a room.");}
public override voidOnConnectedToMaster(){
Debug.Log("PUN Basics Tutorial/Launcher: OnConnectedToMaster() was called by PUN");
PhotonNetwork.JoinRandomRoom();}
public override voidOnDisconnected(DisconnectCause cause){
progressLabel.SetActive(false);
controlPanel.SetActive(true);
Debug.LogWarningFormat("PUN Basics Tutorial/Launcher: OnDisconnected() was called by PUN with reason {0}", cause);}}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using Photon.Pun;
using Photon.Realtime;
public class GameManagerPUN : MonoBehaviourPunCallbacks
{
public override voidOnLeftRoom(){
SceneManager.LoadScene("LobbyScene");}
public voidLeaveRoom(){
PhotonNetwork.LeaveRoom();}}
修改上述 GameManager 脚本如下: 使用 PhotonNetwork.LoadLevel() 而不是 Unity 的场景跳转 使用 OnPlayerEnteredRoom(), OnPlayerLeftRoom() 来监听玩家的进入和离开房间 使用 PhotonNetwork.IsMasterClient 来检测玩家是否在 Master Server ,这之后才能加载到 Game Server
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using Photon.Pun;
using Photon.Realtime;
public class GameManagerPUN : MonoBehaviourPunCallbacks
{
public override voidOnLeftRoom(){
SceneManager.LoadScene("LobbyScene");}
public voidLeaveRoom(){
PhotonNetwork.LeaveRoom();}
private voidLoadArena(){if(!PhotonNetwork.IsMasterClient){
Debug.LogError("PhotonNetwork : Trying to Load a level but we are not the master Client");return;}
Debug.LogFormat("PhotonNetwork : Loading Level : {0}", PhotonNetwork.CurrentRoom.PlayerCount);
PhotonNetwork.LoadLevel("RoomFor"+ PhotonNetwork.CurrentRoom.PlayerCount);}
public override voidOnPlayerEnteredRoom(Player other){
Debug.LogFormat("OnPlayerEnteredRoom() {0}", other.NickName);// not seen if you're the player connectingif(PhotonNetwork.IsMasterClient){
Debug.LogFormat("OnPlayerEnteredRoom IsMasterClient {0}", PhotonNetwork.IsMasterClient);// called before OnPlayerLeftRoomLoadArena();}}
public override voidOnPlayerLeftRoom(Player other){
Debug.LogFormat("OnPlayerLeftRoom() {0}", other.NickName);// seen when other disconnectsif(PhotonNetwork.IsMasterClient){
Debug.LogFormat("OnPlayerLeftRoom IsMasterClient {0}", PhotonNetwork.IsMasterClient);// called before OnPlayerLeftRoomLoadArena();}}}