Photon网络联机

导入插件并配置

中文API地址:

Photon-Network-Documentation-多人在线游戏综合开发文档译文.pdf (vibrantlink.com)

下载、注册账号:

可以在unity资源商店中导入插件。

在Photon官网注册账号,并申请中国区的服务器

 

更换中国服务器地址:

  1. 确保已经申请了中国区服务器。
  2. 在Photon Server Settings 文件中设置服务器地址
  3. 将文件中的区域改成cn,找到LoadBalancingClient.cs脚本,将NameServerHost的后缀改cn

 

连接主服务器、创建房间、加入房间

连接主服务器:

通过PhotonNetwork中的ConnectUsingSettings()静态方法,可以让客户端通过Photon Server Settings 文件中的设置去连接服务器。

 

当然连接服务器的过程不一定是顺利的,如果连接成功或是连接失败Photon都为我们提供了相应的回调。

想要使用这些回调需要继承于MonoBehaviourPunCallbacks类,通过反编译我们可以看到,该类也是继承

MonoBehaviour的,并且实现了很多的接口,这些回调就是来自于这些接口,并且在OnEnable()

与OnDisable()进行绑定,如果不需要使用这么多的话继承某个接口就行。

 

  1. 连接服务器成功的回调OnConnectedToMaster() 

    2. 连接服务器失败的回调OnDisconnected(DisconnectCause cause)(参数为连接失败的原因)

创建房间:

当连接成功之后通过PhotonNetwork.CreateRoom()方法来创建一个房间。参数一:房间的名称可以传null

参数二:通过RoomOptions实例来设置房间的属性比如:

  1. MaxPlayers   房间的最大玩家数量
  2. IsVisible        设置房间是否可见
  3. IsOpen         设置房间是否可以加入
  4. CustomRoomProperties   自定义房间属性,创建一个Hashtable进行添加(游戏模式、地图、密码等)
  5. CustomRoomPropertiesForLobby   基于自定义属性,设置哪些属性在大厅可见

 

当成功创建一个房间之后,我们也可以获取当前房间的属性,比如:

  1. PlayerCount   当前房间中的人数
  2. CustomProperties  创建房间时自定义的属性Hashtable,通过键值对的方式访问

等等. . . .

创建房间成功与失败的回调函数:

创建失败:OnCreateRoomFailed()  在ImatchmakingCallbacks接口中

创建成功:OnCreatedRoom()  在ImatchmakingCallbacks接口中

加入房间:

当客户端创建房间完毕之后,下一步需要做的就是加入房间,不然创建房间干啥?

随机加入房间:

使用PhotonNetwork.JoinRandomRoom();方法随机的加入一个房间,但是得注意如果有些房间有自定义属性,比如说密码,这时我们就不能加入到这些房间之中。所以我们需要对随机加入房间进行一个限制。

参数一:限制一些自定义房间属性通过Hashtable,比如密码为空,前提是创建房间时加入该自定义属性

参数二:限制加入最大人数的房间,如果不需要限制传0即可。

随机加入房间成功与失败的回调函数:

随机加入失败:OnJoinRandomFailed()  在ImatchmakingCallbacks接口中

加入房间成功:OnJoinedRoom()  在ImatchmakingCallbacks接口中

加入指定的房间:

通过PhotonNetwork.JoinRoom(“房间名称”),传入指定的房间名称加入

 

加入指定房间失败执行的回调(加入成功只有一个回调,还是用上面的)

 

游戏大大厅

大厅是一种虚拟的集合,用于对房间进行分类和分组,而不是一个实际的游戏对象,可以通过大厅属性来对房间进行筛选和分组。

在使用PUN时,默认情况下是不会自动加入大厅的,可以使用PhotonNetwork.JoinLobby()方法来加入默认大厅,然后可以使用自定义的属性来对房间进行分组和筛选。这就是一种类似于创建大厅的概念。

 

加入游戏大厅成功的回调OnJoinedLobby()  在IlobbyCallbacks接口中

 

加入大厅成功之后,获取大厅中的房间

当然在创建房间时我们也通过TypedLobby类,来设置大厅类型、名字,

加入大厅时也可以通过JoinLobby()方法的其他重载来选择加入的大厅类型

为了获取大厅中房间数量,PUN只为我们提供了一个当房间列表中房间发生更新时执行的回调

当列表中房间删除新建时会将这些房间通过一个列表传递进回调。通过RoomInfo类获取新加入列表中的房间

是否是移除的,如果不是移除的,我们就添加到新建的房间列表中

 

RoomInfo类代表列表中的房间,从中我们可以获取:

  1. Name  房间名称
  2. PlayerCount  当前房间中玩家的数量
  3. MaxPlayers  当前房间设置的最大玩家数量
  4. CustomProperties  创建房间时自定义的属性,返回Hashtable,比如设定的密码
  5. IaOpen  当前房间是否处于开放状态    等等. . . .

进入房间时输入密码:

通过获取列表中的房间的自定义属性,中的密码具体值,如果空就不输入密码,不为空就需要输入密码

离开游戏大厅的方法

通过调用PhotonNetwork.LeaveLobby()离开游戏大厅

注意:当离开游戏大厅时,客户端需要先清空大厅列表,下次进入大厅时重新加载即可,因为当离开了大厅

我们就获取不到OnRoomListUpdate()当大厅房间发生更新时的回调,当再次进入房间时还是之前的列表,

所以退出时清空,进入时重新获取发生更新的游戏列表

离开游戏大厅成功执行的回调方法 OnLeftLobby()  在IlobbyCallbacks接口中

 

房间内部

当我们创建了一个房间时,这个房间会加入到大厅之中,我们可以获取自身所在的房间的各种信息

通过PhotonNetwork.PlayerList玩家列表,通过遍历它可以获取当前所在房间的所有玩家:

  1. ActroNumber   玩家所在房间内的唯一标识
  2. IsLocal  表示该玩家是否是自己
  3. NickName  玩家的名称
  4. CustomProperties  获取玩家自定义设置的属性值
  5. IsMasterClient  判断当前客户端是否是房主

玩家列表中都是存储值一个个Player类,都是通过这个类来获取上面信息的

除了以上方法可以获取房间内部信息外,我们还可以使用PhotonNetwork.CurrentRoom属性来访问当前玩家所在房间的信息。

该属性类型是Room类继承于RoomInfo类,该类我们在房间发生更新的回调中使用过,代表是一个房间。

  1. Name  当前房间的名称
  2. PlayerCount  当前房间中玩家的数量(不建议使用这个,因为他是无序的)
  3. MaxPlayers  当前房间的最大人数(都是继承RoomInfo类中的属性)
  4. IsOpen  房间是否处于开放状态
  5. IsVisible  房间是否处于开放状态,允许玩家加入
  6. CustomProperties  自定义房间的属性

通过总结在房间内部我们可以获取的信息有:

Player单个玩家信息类。

Room当前房间信息类,因为继承RoomInfo房间信息类

当玩家处于房间之中,当有其他玩家进入房间或者离开时,此时会触发相应回调

可以看到该回调会将Player玩家信息类传递过来,这样我们就可以知道谁进入离开了房间

当自己这个客户端离开房间的回调方法

我们加房间是通过大厅进入的,而离开房间会默认直接回到主页,总之根据自己需求来决定。

当前客户端的网络状态

对于获取客户端的网络状态一般通过PhotonNetwork.NetworkClientState属性来获取,这个属性是一个枚举类型,它的状态有:

  1. PeerCreated:  客户端已经创建,但尚未连接到Photon服务器状态
  2. Queued:  客户端正在等待连接到Photon服务器
  3. Connected:  客户端已成功连接到服务器
  4. ConnectedToMaster:  客户端已成功连接主服务器
  5. Joined:  客户端已成功加入一个房间
  6. JoinedLobby:  客户端以加入大厅
  7. Disconnecting:  客户端正在断开与服务器的连接
  8. Disconnected:  客户端已经断开与服务器的连接

总结:

通过这个属性我们可以实时的获取客户端的网络状态,并根据不同的网络状态做出相应的处理,以便在合适的时机执行相应的状态。

对大厅与房间做进一步总结

创建房间时我们指定房间名称、房间自定义属性、房间所属大厅类型(TypedLobby类)。

玩家可以选择进入某个类型的大厅。进入大厅之后我们便能够通过OnRoomListUpdate(List<RoomInfo> roomList)回调函数来获取当前大厅中的房间数量,这个回调函数只有在大厅房间发生更新时调用。

通常情况下我们通过遍历他的列表来获取所有房间信息。

需要注意的是:我们可以创建很多类型的大厅,但是这个回调函数只会传入你加入的某个类型的大厅中的房间数量。

属性同步

  1. 通过:PhotonNetwork.LocalPlayer.SetCustomProperties()修改玩家自定义属性
  2. 通过:PhotonNetwork.CurrentRoom.SetCustomProperties()修改当前房间的

当我们修改玩家和客户端的属性是,我们可以通过回调函数的方式同步给其他客户端

我们可以通过获取变更的属性,从而设置给对应玩家或房间,实现玩家的属性同步。

当然一般情况来说,设置当前房间的属性的变更由主客户端来决定,其他的只需同步数据即可

网络游戏对象

Photon View组件:

为了使一个游戏对象能够在网络中同步,需要将PhotonView组件添加到该游戏对象上,只有添加了这个组件

才能称之为网络对象。

 

基本信息:

  1. ViewID:每个PhotonView都有一个唯一的ViewID,这个是通过Photon网络进行分配的,并且在整个

网络中保持唯一性。

  1. Ownership:当前游戏对象的所有权,指的是某个客户端对游戏对象的控制权。固定的、可以主动附加给别人、其他客户端可以请求控制权。
  2. Synchronization:同步,我们可以选择同步的类型是可靠的还是不可靠的。
  3. ObservableSearch:寻找同步哪种类型的组件。手动添加、查找激活的、查找所有

生成一个网络游戏对象:

生成方式有两种:

  1. PhotonNetwork.Instantiate()  该方法用于在所有客户端上去实例化一个对象,并且所有的客户端都会同步它,该方法适用于所有需要同步显示的对象。
  2. PhotonNetwork.InstantiateRoomObject()  该方法用于在房间内实例化一个网络对象,但只有主客户端会

生成这个对象,其他客户端等待主客户端生成后并等待同步。

注意:在unityAPI中使用这个方法传入的是一个GameObject,但是在Photon中需要传入的是在Resurces文件夹下的路径中GameObject。

通过该方法生成的游戏对象,谁生成的游戏对象这个对象的权限就归谁。

 

同步组件

使用后Photon实现同步非常简单,Photon为我们提供好的同步组件有:

只需添加对应的组件就能同步unity中对应的组件。

当然这些组件都是通过PhotonView组件进行同步的,上面也说了:在PhotonView中可以选择同步的类型

使用PhotonView组件我们并不需要先去获取,在MonoBehaviourPun基类中已经帮我们提供好了属性

那在我们的脚本中PhotonView也为我们提供了一些方法和属性:

常用属性:

  1. View ID:用于获取PhotonView对象的唯一ID。
  2. IsMain:用于检查PhotonView对象的所有权是否是当前客户端。
  3. IsSceneView:用于判断是否是主客户端对象,是否是主客户端创建的。
  4. IsRoomView:是否是房间对象(其实就是判断该网络对象是用哪个方法生成的)
  5. Owner:当前网络对象的所有者(指控制它的客户端)等等. . . .

常用方法:

  1. RPC():网络函数,用于在不同客户端之间调用函数,通过RPC可以让一个客户端调用其他客户端上的函数。参数一:函数名称(函数前面需要加上[PunRPC]特性),参数二:指定哪些客户端可以调用,参数三:

调用该函数的参数。该函数通过反射调用建议不要频繁使用。

 

其中一个客户端使用了该函数,那么其它客户端会在这个目标客户端上执行相应函数,不需要我们手动进行调用。

  1. TransferOwnership()转移所有权,将一个网络对象从当前的拥有者转移给其他玩家。

等等. . . .

自定义同步组件:

主要两个步骤:

第一步:让自定义脚本实现IpunObservable接口

第二步:实现接口里面的OnphotonSerialize(PhotonStream stream, PhotonMessageInfo info)方法

只要当前自定义脚本中的属性发生改变时就会调用该函数

在该回调中最为重要的是PhotonStream数据流参数,一个客户端将数据写入到这个数据流之中,然后将数据流发送给其他客户端,这样其他客户端就可以从数据流中读取数据。

这个参数一般这样用:

写入者(发生改变的客户端):当对象的某个属性发生改变时,这个客户端会将这些改变写入到字节流之中,然后发送给服务器,以便将这些改变同步给其他客户端。

读取者(没有发生改变的客户端):其他客户端接收这些数据流,然后从数据流中读取属性的改变,如果一个客户端的属性没有发生改变,那么在读取数据时,它仅仅是接收数据流中的属性值,而不会写入数据流。

PhotonStream类中的常用属性有:

  1. IsWriting:判断当前数据流是否正在写入
  2. IsReading:判断当前数据流是否正在读取
  3. Count:用于获取当前字节流的个数
  4. SendNext():该方法用于将一个值写入到数据流之中,当前客户端发生改变时可以使用
  5. ReceiveNext():该方法用于读取一条数据,一般在没有发生改变的客户端使用
  6. PeekNext():类似于ReceiveNext()但是只会读取不会导出

使用CustomProperties同步:

我们可以通过这种方式设置房间或玩家的自定义属性,通过回调方法来获取属性是否发生改变。

设置房间或玩家自定义属性:

因为CustomProperties的类型是一个Hashtable所以可以直接设置

通过SetCustomProperties()方法设置自定义属性

获取自定义属性(一般用于接收到服务器消息之后,进行判断是否为Null)

通过这样的方式,如果玩家修改了自定义属性,它会把这个消息发送给服务器。服务器再将消息发送给各个客户端,各个客户端触发回调后分别设置其他网络对象的状态。(回调函数在属性同步时说过)

强调:玩家不会直接修改客户端的属性,而是通过服务器同步和回调来实现属性的更新。

通过事件广播的形式同步:

PhotonNetwork.RaiseEvent()发起事件:

参数一:0到255之间,用于识别不同的事件类型,主要给其他的客户端使用

参数二:这是一个object数组,是主要传递的数据,可以放置任何的数据

参数三:RaiseEventOptions用于指定事件的接收者,或是规定是否缓存数据,当其他的客户端再次进入房间

              时,会将缓存的事件发送给这个客户端。

参数四:SendOptions用于选择网络协议的可靠性,一般UDP/TCP

通过这样的方式只要在需要的时候就能广播给其他的客户端

事件接收

接收发送的事件需要脚本中实现IOnEventCallback接口,并重写其中的OnEvent的方法。这个方法会在客户端接收到消息的时候调用,我们可以在其中处理接收到的事件数据。

该方法会通过EventData传递过来数据,从中可以得到的数据有:

  1. CustomData:发送过来的数据(需要转换一下使用)
  2. Code:发送的事件的编号
  3. Sender:事件的发送者(发送事件的客户端)

总结

通过使用Photon我们能够快速的实现网络联机基本步骤如下:

  1. 连接服务器:一般通过PhotonServerSettings的配置来连接,连接成功失败都有对应的回调
  2. 创建房间:我们可以设置房间名称或自定义属性、以及选择大厅类型。成功失败都有对应回调
  3. 进入大厅:可以选择所进入大厅的类型,通过大厅房间发生更新的回调获取房间列表中房间的数量,进入成功失败都有回调
  4. 进入房间:我们可以通过名称进入指定房间或是随机进入房间,通过PlayerList属性获取玩家数量,通过PhotonNetwork.CloseConnection()踢出指定客户端
  5. 场景跳转:使用PhotonNetwork.LoadLevel(),当前房间内所有客户端一起跳转,单独一个客户端跳转使用unity的方法。
  6. 生成网络对象,PhotonView组件,通过PhotonNetwork.Instantiate()生成,才能决定操控对象
  7. 同步方式:属性同步CustomProperties、方法同步RPC()、组件同步、事件同步
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值