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来监听房间属性发生变化
更多信息请参考官方文档。
PhotonServer入门教程相关推荐
- Kafka入门教程与详解
1 Kafka入门教程 1.1 消息队列(Message Queue) Message Queue消息传送系统提供传送服务.消息传送依赖于大量支持组件,这些组件负责处理连接服务.消息的路由和传送.持久 ...
- 【CV】Pytorch一小时入门教程-代码详解
目录 一.关键部分代码分解 1.定义网络 2.损失函数(代价函数) 3.更新权值 二.训练完整的分类器 1.数据处理 2. 训练模型(代码详解) CPU训练 GPU训练 CPU版本与GPU版本代码区别 ...
- python tornado教程_Tornado 简单入门教程(零)——准备工作
前言: 这两天在学着用Python + Tornado +MongoDB来做Web开发(哈哈哈这个词好高端).学的过程中查阅了无数资料,也收获了一些经验,所以希望总结出一份简易入门教程供初学者参考.完 ...
- python向量计算库教程_NumPy库入门教程:基础知识总结
原标题:NumPy库入门教程:基础知识总结 视学算法 | 作者 知乎专栏 | 来源 numpy可以说是 Python运用于人工智能和科学计算的一个重要基础,近段时间恰好学习了numpy,pandas, ...
- mysql query browswer_MySQL数据库新特性之存储过程入门教程
MySQL数据库新特性之存储过程入门教程 在MySQL 5中,终于引入了存储过程这一新特性,这将大大增强MYSQL的数据库处理能力.在本文中将指导读者快速掌握MySQL 5的存储过程的基本知识,带领用 ...
- python tensorflow教程_TensorFlow入门教程TensorFlow 基本使用T
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 TensorFlow入门教程 TensorFlow 基本使用 TensorFlow官方中文教程 TensorFlow 的特点: 使用图 (graph) 来 ...
- air调用java,AIR2.0入门教程:与Java应用交互
在之前的一篇文章中,我介绍了如何使用AIR2.0新增的NativeProcess类与本地进程进行交互和通讯,在那个例子里面我们使用了C++ 的代码,实际上只要是基于命令行的标准输入输出,AIR2.0的 ...
- 【Arduino】开发入门教程【一】什么是Arduino
Arduino Arduino 是一款便捷灵活.方便上手的开源电子原型平台,包含硬件(各种型号的arduino板)和软件(arduino IDE).它适用于艺术家.设计师.爱好者和对于"互动 ...
- python 三分钟入门_Cython 三分钟入门教程
作者:perrygeo 译者:赖勇浩(http://laiyonghao.com) 原文:http://www.perrygeo.net/wordpress/?p=116 我最喜欢的是Python,它 ...
最新文章
- fflush(stdin)和fflush(stdout)和rewind(stdin)的区别和作用
- 已完结 | PMCAFF深度报告:《 典典养车如何在一年内做到600万用户、三轮融资、覆盖40城市》
- 如何展示富文本_自助建站如何做出个性化效果?
- vue 子组件 调用、触发父组件中的方法
- 关于RabbitMQ以及RabbitMQ和Spring的整合
- mongodb ensureIndex parameter
- Manacher算法 - 求最长回文串的利器
- 老段工作室成立两周年
- 软件工程——软件计划
- 如何计算信号的信噪比
- CodeSmith链接Oracle、MySQL数据库
- python网课培训班学费一般多少
- BASH脚本基础:语法检查与调试
- windows server 2012 进程 出现大量桌面窗口管理器的 解决方法
- 语音识别(一)——概述
- 如何区别计算机体系结构与计算机组成这两个概念?
- python爬虫beautifulsoup爬当当网_利用python爬虫可视化分析当当网的图书数据!
- 【目标检测】YOLO v5 吸烟行为识别检测
- SenseTime Ace Coder Challenge 暨 商汤在线编程挑战赛-白色相簿
- 【帝国CMS插件】支持7.5 7.2 移动同步生成插件 帝国多端访问必备插件带详细安装教程
热门文章
- Android 极光IM简单的聊天界面全手动实现
- 【matlab深度学习数据归一化处理】
- Itext图层合并/分离
- 安装flash后仍然提示“您的计算机尚未安装Flash”
- 推荐给12星座的魅力小蛋糕(组图)
- FP-growth算法通俗讲解
- 【可食用】KeyTool生成KeyStore,证书、公钥、私钥文档JAVA生成,JAVA实现ECC签名验签
- GE LIGHTSPEED VCT型CT机怎样修改WORKLIST参数
- 基于嵌入式平台下的GIS/GPS定位系统设计 之 设计方案选择
- 利用计算流体力学(CFD)方法求解流场