PhotonServer入门教程

一、photonserver简介

由于unity官方自带的UNET多人联机模块停止维护,并且在将来的版本将弃用,新的联机模块尚未发布,所以目前unity上做多人联机一般用第三方方案,photonserver就是一个比较流行的unity多人联机解决方案,下面主要介绍一photonserver。

photonserver分为服务端sdk和客户端sdk,客户端sdk再资源商店可以免费下载,叫PUN2,服务端sdk在官网下载

photonserver的服务器应用安装成功后,会自带一个叫(LoadBalancing)MyCloud的服务,启动这个服务,photonserver内部会启动一个master和一个gameserver服务(根据配置也可以只启动其中一个),master可以理解成大厅服务,gameserver就是具体的房间服务器,这个服务是官方给我们实现的可以通用的服务器程序,也是photonCloud服务器上运行的程序,所以实际上我们可以用photonServer程序搭建自己的photonCloud,也就是为什么这个服务要叫mycloud,我们可以按照photonserver提供的一些示例,开发自己的服务器程序,而且服务器程序的开发也是使用C#语言,客户端程序员学起来也不会特别吃力,但是目前我们使用自带的mycloud 做为服务器程序就已经能够实现基本的多人联机功能了,所以对服务器程序开发我们先掠过,直接开始介绍如何使用客户端的pun sdk与mycloud 服务来实现多人联机功能

 

photon的mycloud服务为什么能通用

因为mycloud只提供公共的功能,比如master只负责例如记录玩家信息,分配房间,匹配玩家等通用功能,gameserver只提供消息转发功能。由于不涉及任何业务逻辑,因此可以做为通用服务器,业务逻辑都由客户端自己处理,因此这种服务器架构,不能很好的处理作弊问题。值得注意的是一个gameserver并不是只对应一个房间,一个gameserver能容纳的最大玩家数量跟机器硬件性能和游戏消息大小及发送频率有关,gameserver内部通过玩家所属房间来对玩家进行分组,确定消息转发边界。

 

既然只是转发消息,为什么要使用photon服务器,而不是自己写一个消息转发服务

photon的同步方式除了一般的消息转发,还提供了RPC的方式,使用更加方便;photon实现了一个可靠的udp协议,在需要转发可靠消息时,比直接使用tcp协议更有效率;另外photon提供了负载均衡的功能,通过简单的配置,一个master服务可以对接到多台其他机器上运行的gameserver服务,玩家建立房间时会自动被转到相对空闲的gameserver服务器上,可以动态添加gameserver服务器的数量,适配不同玩家规模的需求;除此之外photon提供了unity客户端插件PUN,封装了一些常用方法和组件,很多功能的实现甚至不用写代码,极大的提高了联网模块的开发效率。

 

服务器程序部署:https://vibrantlink.com/5minsphotonserver/

一个mater对多个gameserver的配置方式:https://www.cnblogs.com/cj8988/p/11731428.html

Pun官方文档:https://doc.photonengine.com/en-us/pun/current/getting-started/pun-intro

二、使用步骤

配置服务器ip端口

PhotonNetwork.PhotonServerSettings.AppSettings.Server =  "127.0.0.1";

PhotonNetwork.PhotonServerSettings.AppSettings.Port = 5055;

PhotonNetwork.PhotonServerSettings.AppSettings.UseNameServer = false;

除了这种代码中设置外,还可以在pun sdk的配置文件中设置,如下图

需要注意的是使用自己部署的photonserver而不是photoncloud时,不能勾选useNameServer,如果勾选这个选项,pun 会根据你填的fixedRegion去连接对应的nameserver,nameserver会返回一个自己管理范围内ping值最低的photonCloud服务器ip和端口,pun会去连接这个服务,而不是我们自己部署的服务。

发起连接

配置好连接参数后,使用PhotonNetwork.ConnectUsingSettings()来发起连接,通过实现IConnectionCallbacks接口,并使用PhotonNetwork.AddCallbackTarget(this);来注册监听器,可以获取到连接相关的回调信息,当回调成功后,此时只是连接上master服务器,还没有将玩家加入到大厅当中,玩家对其他在大厅中的玩家还不可见,调用 PhotonNetwork.JoinLobby()完成加入大厅的过程,同样通过实现ILobbyCallbacks并注册监听,可获取相关回调。

创建房间

使用PhotonNetwork.CreateRoom(string roomName,RoomOptions option, TypedLobby.Default)来创建房间,roomName为自定义房间名称,是房间的唯一标识,不能重复,roomOption是房间的一些参数,例如房间最大人数,是否可见等,也可以设置一些自定义参数,如房间密码等,这些参数对大厅的玩家可见,在加入房间前可进行一些判断。通过注册IMatchmakingCallbacks获取相关回调

加入房间

调用PhotonNetwork.JoinRoom(string roomName)方法加入房间,还有其他几种加入房间的方式,如随机加入,加入或创建房间等函数,具体参考api文档,同样通过实现IMatchmakingCallbacks获取相关回调。

消息同步

PhotonView的使用

大部分情况下,场景中所有需要同步状态的物体上面,都需要挂载PhotonView组件,如下图

PhotonView组件可以监听实现了IPunObservable接口的脚本,Pun提供了两个可监听的脚本PhotonTransformView和PhotonAnimatorView,挂载上面两个脚本并使用PhotonView监听就可以实现简单的位置同步和动画同步(PhotonAnimatorView同步trigger类型的动画参数时不太好用,必须将PhotonAnimatorView挂载在物体组件的最后一个位子,且设置trigger的代码必须在update函数中,不然PhotonAnimatorView监听不到tigger变化,有兴趣的同学可以自己研究原因)。我们也可以用自己的脚本实现IPunObservable来同步一些自定义数据,使用方法参考api文档。

新建和销毁GameObject

动态创建网络GameObject时使用如下代码

gameObject = PhotonNetwork.InstantiateSceneObject(prefabName,Vector3.zero,Quaternion.identity)

PrefabName为预制体名称,预制体必须放置在resource目录,下如果要在创建物体后进行一些参数设置,可以在像这样

System.Object[] objectParams = { PhotonView.Get(this).ViewId}

material = PhotonNetwork.InstantiateSceneObject(contentPrefab,Vector3.zero,Quaternion.identity,0,objectParams)

然后在实例化物体上的脚本实现IPunInstantiateMagicCallback接口,在OnPhotonInstantiate方法里设置参数,如下

public void OnPhotonInstantiate(PhotonMessageInfo info)
{
    if(info.photonView.InstantiationData.Length == 1)
    {
        info.photonView.transform.parent = PhotonView.Find((int)info.photonView.InstantiationData[0]).transform;
    }
}

销毁GameObject

PhotonNetwork.Destory(box.GetComponent<PhotonView>());

RPC

声明

[PunRPC]
private void MyRPCMethod(){}

RPC方法所在的脚本必须和photonview脚本挂载同一个物体上

调用

PhotonView.Get(this).RPC("MyRPCMethod",RpcTarget.MasterClient);

RPCTarget可选项有多种,可以只发送给主机,或者主机以外的玩家,或者所有人,并且可以选择是否缓存此条rpc信息,如果是带缓存的RPC,后面进来的玩家也能收到这条消息,但是需要注意缓存的容量,必要时清除缓存。

自定义消息

定义消息内容和序列化和反序列化方法,第二个参数为消息类容编号,光子最多支持256种自定义消息内容类型,建议从255往下取,其中有4种是默认类型,具体参考:

https://doc.photonengine.com/en-us/pun/current/reference/serialization-in-photon#additional_types_in_photon_unity_networking

 

PhotonPeer.RegisterType(typeof(CustomClass),255,CustomClass.Serialize,CustomClass.Deserialize);

发送消息

第一个参数是消息编号,取值1-199,200-256为photonServer内部占用,第二个参数为发送的消息类容,除了默认支持的类容类型,其他类型需要在上一步先注册。

RaiseEventOptions rasieEventOptions= new RasieEventOptions{Receivers = ReceiverGroup.Others};

SendOptions sendOptions = new SendOptions{Reliability = false};

PhotonNetwork.RaiseEvent(1,new CustomClass(),rasieEventOptions,sendOptions );

接受消息:实现IOnEventCallback接口,在OnEvent函数中接受消息房间属性

public void OnEvent(EventData photonEvent)
{
    if(photonEvent.Code == 1)
    {
        CustomClass data = (CustomClass)PhotonEvent.CustomData;
    }
}

房间属性 

房间属性是一个hashtable,可存储一些自定义数据,设置后会自动同步到同房间的其他玩家, 具体支持数据类型参考api文档,设置房间属性时,有一个可选参数,叫做期望值,也是 hashtable,设置了此属性后,服务器上进行房间属性设置时,会检测当前的期望值中的 key 在房间属性中是否存在且value是否一致,只有都一致时,此次房间属性设置才会生效,该方法可用来处理不同客户端的并发设置问题,比如两个玩家几乎同时触碰到一个道具,在决定道具归属时,应该是谁先接触谁获得,但是如果不用期望值,则明显后接触的玩家会获得道具(因为房间属性的值是最后一次修改的值),这时修改房间属性中道具所属玩家id时,可带上期望值,当前道具所属玩家id为默认值时,才修改所属,这样先接触的玩家能修改成功,后接触的玩家就修改失败了。

设置房间属性

                ExitGames.Client.Photon.Hashtable expectedProperties = new ExitGames.Client.Photon.Hashtable();

                ExitGames.Client.Photon.Hashtable roomCustomProperties = new ExitGames.Client.Photon.Hashtable();

                expectedProperties[itemRole.m_CurrentRoleData.RoleID] = clickEvent.actorNumber;

                roomCustomProperties[itemRole.m_CurrentRoleData.RoleID] = -1;

                PhotonNetwork.CurrentRoom.SetCustomProperties(roomCustomProperties, expectedProperties);

设置房间属性后,实现并注册IInRoomCallbacks接口的OnRoomPropertiesUpdate来监听房间属性发生变化

玩家属性

同房间属性,只是维度是玩家而不是房间

设置玩家属性

        ExitGames.Client.Photon.Hashtable playerCustomProperties = new ExitGames.Client.Photon.Hashtable();

        playerCustomProperties.Add("account", AccountManager.Instance.m_CurrentAccount.AccountNumber);

        playerCustomProperties.Add("name", AccountManager.Instance.m_CurrentAccount.Name);

        playerCustomProperties.Add("roleId", string.Empty);

        PhotonNetwork.LocalPlayer.SetCustomProperties(playerCustomProperties);

设置玩家属性后,实现并注册IInRoomCallbacks接口的OnPlayerPropertiesUpdate来监听房间属性发生变化

 

更多信息请参考官方文档。

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值