文章目录
- 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
修改继承类以重写回调函数 把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确定登录成功后,
- 把账号保存到
PlayerPrefs
哈希表里(记住账号方便以后输入)。 - 设置
PhotonNetwork.NickName
,再调用Connect()连接。 - 若连接成功则跳转场景(确保登录场景中的GameFace物体保留、那上面挂载着socket脚本)。
- 连接失败则UI提示。
游客线上模式仍然需要存储在PlayerPrefs里的,尽量方便每次重新打开游戏时的使用,不用再需要用户手动输入。
游客模式下的GUI可以参考PUN Basics Tutorial–2–Creating The UI For The Player’s Name。
在InputField上挂在一个脚本并且实现OnValueChanged
回调函数实时设置PhotonNetwork.NickName
和保存到PlayerPrefs
。
在开始连接之后,从人机交互角度上来说,有一个动画效果显示当前正在连接会带来更好的体验,同样这也是官方所建议的。
这通过SetActive()
就可以随意控制,当然稍微复杂点也可以实现自己的UI代码框架进行弹出窗体。