文章目录

  • Photon Unity Networking简介
  • PUN2基础&Lobby/Room
  • 玩家昵称


Photon Unity Networking简介

Pun2是一个API很简单的多人游戏开发框架。
可以通过继承pun框架提供的类或实现其各种接口与unity项目融合实现多人联机。
… …

PUN2基础&Lobby/Room

Unity基础知识不过多赘述。
从MonoBehaviour中派生出的类,MonoBehaviour本质上将我们的类变成了一个Unity组件,然后我们可以将它放到游戏对象或预设上。扩展MonoBehaviour的类可以访问许多非常重要的方法和属性。比如Start()等回调函数。

我们的游戏将有一个基于玩家数量的可调整大小的房间功能,为了确保加载的场景对于每个连接的玩家都是相同的,我们将利用Photon提供的PhotonNetwork.AutomaticallySyncScene可见下例代码)。当这个变量为true时,主客户端可以调用PhotonNetwork.LoadLevel(),所有连接的玩家都会自动加载相同的关卡。

PUN对于回调非常灵活,并且提供了两种不同的实现(继承MonoBehaviourPunCallbacks类/单独实现接口)。为了便于学习,让我们涵盖所有方法,我们将根据具体情况选择最适合的方法。其中继承类是最简便的一种方法。

新建脚本
编写连接服务器方法
添加using Photon.Pun;,代码如下:

#region Private Fields
        //版本控制,不同版本的玩家会被隔离开。应该是能实现多版本在线,相同版本之间才能匹配,不会出现某个玩家缺少资源而崩溃的情况吧
        string gameVersion = "1";
        #endregion

        #region MonoBehaviour CallBacks
        void Awake()
        {
            //自动同步场景,当这个变量为真时,主客户端可以调用PhotonNetwork.LoadLevel()和所有连接的玩家都会自动加载相同的关卡。
            PhotonNetwork.AutomaticallySyncScene = true;
        }

        void Start()
        {
            Connect();//调用了下面的一个公共方法
        }
        
        #endregion
        
        #region Public Methods
        public void Connect()
        {
            if (PhotonNetwork.IsConnected)
            {
                // #Critical we need at this point to attempt joining a Random Room. If it fails, we'll get notified in OnJoinRandomFailed() and we'll create one.
                PhotonNetwork.JoinRandomRoom();
            }
            else
            {
                //连接Photon服务器
                PhotonNetwork.ConnectUsingSettings();//使用设置(服务器区域、游戏版本等),见下图。
                PhotonNetwork.GameVersion = gameVersion;
            }
        }


        #endregion

unity多人同屏游戏 unity多人联机游戏_服务器

修改继承类以重写回调函数MonoBehaviour修改为MonoBehaviourPunCallbacks,这个类既有MonoBehaviour的特性又有各种Pun接口的特性。所以继承之后再实现接口实际上也是去override回调方法。
添加命名空间引用 添加using Photon.Pun; using Photon.Realtime;编写回调函数
写一个连接到主服务器的回调函数和断开连接的回调函数。对于每一种情况都应该实现回调函数,以做出相应,增加软件的5E特性。同时也是良好的人机交互的必要条件。
对于众多的回调函数可以用#region …和#endregion包围起来,更好的查看代码。

public override void OnConnectedToMaster()
{
    Debug.Log("PUN Basics Tutorial/Launcher: OnConnectedToMaster() was called by PUN");
}


public override void OnDisconnected(DisconnectCause cause)
{
    Debug.LogWarningFormat("PUN Basics Tutorial/Launcher: OnDisconnected() was called by PUN with reason {0}", cause);
}

若连接成功则调用加入房间
现在已经知道是否加入到了主服务器。
如果连接到了服务器那么就可以开始涉及到大厅与房间了,按照官方教程,大厅暂时不去详细的写。因为还涉及到GUI。下面先试着直接加入房间。

PhotonNetwork.JoinRandomRoom();

房间的回调
但是如果此时没有任何一个房间,那么必然会报错,而且我们也无法得知是否加入房间成功。
因此这里就需要房间相关的回调函数了。

//如果加入房间失败了--没有空闲房间--则创建房间,如下代码使用的默认的参数设置。
public override void OnJoinRandomFailed(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());
    //创建一个房间并加入
}

//加入房间成功的回调函数
public override void OnJoinedRoom()
{
    Debug.Log("PUN Basics Tutorial/Launcher: OnJoinedRoom() called by PUN. Now this client is in a room.");
    //成功加入房间了,可以实现别的事情,比如在聊天框中输出“xxx 加入了房间”等任何需要的事情
}

tips:具体各种可能的状况后续编写应对,此处根据官方文档进行最关键的回调方法进行学习。


暴露私有变量到unity的inspector面板
在变量上方加上标签:[SerializeField]。
有些变量通过代码来编写其值可能不会特别方便或者有时候更合适inspector面板里手动去设置其值。
比如private byte maxPlayersPerRoom = 4; 这个值确实可以应用到每个房间的设置上。用以限定房间最大玩家数。
另外可以在此变量上方添加一个注释:[Tooltip(“注释”)]。

现在就可以通过实例化RoomOptions对象时设定最大玩家数,需要了解的是,此时不再是构造函数进行实例化。反而是大括号内书写这个类中的公共变量的定义。

//现在不仅创建了房间,还通过设定建立了一个具有最大玩家数的房间。
PhotonNetwork.CreateRoom(null, new RoomOptions { MaxPlayers = maxPlayersPerRoom });

现在在代码中使用了maxPlayerPerRoom的值去创建一个房间。如果人满了,那么这个房间将不再接收其他人的加入。


现在可以做一个UI,当点击按钮时(比如登录)再连接这个服务器。
这么做算是unity基础了,不多说。

玩家昵称

下面进行玩家昵称的相关代码编写。
官方文档是针对随意设置昵称,不讲求账号的区别性的教程。与项目内容有点出入。
下面按照所学,结合项目需求进行改写:(昵称即账号)
首先说明一下执行逻辑:
玩家点击登录 → 向自开发服务端发送pack → 若验证成功 → 玩家客户端将登录账号作为昵称然后连接pun服务端。

此时就需要一个变量保存玩家账号。
当解析完服务端发来的pack确定登录成功后,

  1. 把账号保存到PlayerPrefs哈希表里(记住账号方便以后输入)。
  2. 设置PhotonNetwork.NickName,再调用Connect()连接。
  3. 若连接成功则跳转场景(确保登录场景中的GameFace物体保留、那上面挂载着socket脚本)。
  4. 连接失败则UI提示。

游客线上模式仍然需要存储在PlayerPrefs里的,尽量方便每次重新打开游戏时的使用,不用再需要用户手动输入。
游客模式下的GUI可以参考PUN Basics Tutorial–2–Creating The UI For The Player’s Name。
在InputField上挂在一个脚本并且实现OnValueChanged回调函数实时设置PhotonNetwork.NickName和保存到PlayerPrefs

在开始连接之后,从人机交互角度上来说,有一个动画效果显示当前正在连接会带来更好的体验,同样这也是官方所建议的。
这通过SetActive()就可以随意控制,当然稍微复杂点也可以实现自己的UI代码框架进行弹出窗体。