5分钟部署PhotonCloud
关于PhotonCloud光子云的区域问题
在您默认开始使用PhotonCloud光子云的时候,区域会被默认为海外区域,这可能会严重影响您游戏的连接速度和网络品质。在您通过中国区邮件申请发送到您的账号名,联络方式和appid给我们之后,1-2个工作日内,我们将为您免费开通中国区的PhotonCloud光子云服务(初始限定为20CCU)。
快速开始
在这篇文章中,您将掌握迅速部署PhotonCloud光子云,并着手于我们的Demo“粒子演示”。 我们的SDK附带的演示向您展示了如何在一般的应用环境中如何添加多人功能。 我们将看看基本的Photon操作,并且有什么您马上安装就能使用的便捷功能。
虽然下面的C#代码示例是有点专门针对于Photon Unity3D SDK( 下载 )的,但是下面的基本工作流程(1) 连接 ,(2) 创建房间和(3) 发送事件在各平台的应用之间是通用的。
核心内容
- 1)连接到主服务器
- 2)创建房间/加入房间
- 3)发送活动
连接到主服务器
您需要做的第一件事是将您的客户端连接到云端(光子云)。 我们将此过程称为连接到主服务器。 从那里,主服务器将负责所有客户端到游戏服务器的传输,云中的负载平衡功能负责协调所有可用的房间。
让我们直接进入我们的演示代码:
// From GameLogic.cs public GameLogic(string masterAddress, string appId, string gameVersion) : base(masterAddress, appId, gameVersion) { this.LocalPlayer.Name = "usr" + SupportClass.ThreadSafeRandom.Next() % 99; this.AutoJoinLobby = false; this.UseInterestGroups = true; this.JoinRandomGame = true; this.DispatchInterval = new TimeKeeper(10); this.SendInterval = new TimeKeeper(100); this.MoveInterval = new TimeKeeper(500); this.UpdateOthersInterval = new TimeKeeper(this.MoveInterval.Interval); }
GameLogic类继承了LoadBalancingClient ,它保持一个状态并自动执行主服务器和游戏服务器之间的转换。 让我们仔细看看GameLogic构造函数中使用的参数:
- string masterAddress :要连接的(主)服务器的URL。 请参阅Photon云区域列表 。
- string appId :在我们的云系统中标识您的应用程序。 如果您还没有AppId,您可以在Photon Cloud信息中心 创建。 您需要插入有效的AppId才能使大多数演示工作。
- string gameVersion :一个字符串,你可以选择曲隔你的游戏的不同版本。 只有具有相同版本号的客户端可以匹配,并且可以相互通信。 这使得添加功能更容易,不会破坏旧客户端。
连接后,Photon云已准备好遵照你的吩咐。 你不必去做所有细微的调整,因为一切都已经为你处理好了! 在下面的图表中,您可以看到,灰色方块中的所有内容都是由Photon Cloud组织的。 客户端只需要发送简单的操作,如箭头旁边的那些。
现在我们连接到主服务器,我们可以列出,创建和加入房间。 在这一点上,玩家不能相互通信或交互。 这是房间的概念发挥作用。 仔细想一想,看看你需要做什么来连接玩家彼此。
大厅,创建房间和加入房间
默认情况下,当你连接时,LoadBalancing API会让你进入游戏的“Lobby”。 在大厅中,主服务器向客户端提供房间列表。 为了保持例如移动环境中的低流量,客户端不能在大厅中互相交互。
一个房间可以被认为是一个单独的区域,玩家互动(玩他们的游戏)。 当他们在同一个房间,玩家可以发送和接收来自其他人的事件,更改/更新房间的属性等。
在下面的示例中,我们使用“OpCreateRoom”操作来创建和打开房间。 一起创建一个:
RoomOptions options = new RoomOptions(); options.options.maxPlayers = 4; peer.OpCreateRoom("Room 42", options, TypedLobby.Default);
最需要留意的参数和RoomOptions是:
- string roomName房间的名称,用于标识和加入房间。
- bool.RoomOptionsisVisible此变量确定房间是否在可在大厅可见的房间列表中(即连接到主服务器但还没注册但还没有进入房间中的玩家可见)。 重要的是,这些房间仍然可以加入,只要客户端知道房间的确切名称。
- bool RoomOptions.isOpen确定客户端是否可以加入房间。 当此变量改变时,已经在房间中的客户端不受影响。 然而,他们不能在离开后重新加入房间,只要isOpen是False的。
- byte RoomOptions.maxPlayers决定此房间中的最大玩家数。 如果设置为0,则上限是无限的。 请注意,如果你计划在一个房间里放入大量的用户,你应该看看我们的Photon服务器MMO应用程序!
- Hashtable RoomOptions.customRoomProperties是一组可选的键和值,您可以定义它们来描述房间。 一个可选的示例是:key“level”,值为“de_dust”。(^_^)。 属性将同步到房间中的所有客户端,并在配对中发挥作用。 更多关于这个选项,见下面。
- string [] RoomOptions.customRoomPropertiesForLobby将在Lobby中显示的属性。
使用Photon,您可以在运行时更改房间或玩家的属性,因此通过customGameProperties设置属性,在设计服务器逻辑时你将不会有任何限制 。 在房间中使用room.SetCustomProperties(props)设置新值或覆盖现有值。 所做的更改将被合并,因此您只需要传入您想要更改的属性即可。
一个房间可以有许多属性,但通常只有几个是玩家配对所需要的,所以Photon会希望你在大厅里面定义一个房间的属性关键列表。 即使在RoomOptions.customRoomProperties中尚未定义的键也可以在string [] customRoomPropertiesForLobby中使用,并在稍后填充。
就像是房间的属性一样,您可以为每个玩家设置自定义属性。 每个客户端可以设置玩家属性LoadBalancingClient.localPlayer.SetCustomProperties() ,即使在加入房间之前。 他们一直保留客户端,并与客户端加入或创建的任何房间时保持同步。
现在我们成功创建了一个房间,是让其他客户加入的时候了! 加入房间是非常快速和容易的,不需要任何进一步的解释,看看下面的操作:
// From LoadBalancingClient.cs public void OnOperationResponse(OperationResponse operationResponse) { ... this.OpJoinRoom(name); }
接下来让我们看看玩家现在可以如何互动。
发送事件
对于客户端彼此交互,我们使用一个简单的事件系统。 使用事件是向给指定房间内的玩家发送和接收快速可靠信息的主要方式。 所有你游戏逻辑中的重要活动都可以通过这种方式进行传递。您的游戏逻辑的所有必要的数据可以在客户端之间发送。 您甚至可以通过使用简单的参数指定协议(UDP与TCP或可靠的(UDPreliable UDP)与不可靠的UDP(unreliable UDP))来自定义交换信息的方式,具体取决于您的需要。
活动将在房间的参与者之间分发。 您可以决定是否要将活动发送到特定的玩家,团体或个人的列表。
让我们来看看我们在粒子演示中使用的事件,例如在更改颜色时:
public void ChangeLocalPlayercolor() { if (this.LocalPlayer != null) { this.LocalPlayer.RandomizeColor(); this.loadBalancingPeer.OpRaiseEvent(DemoConstants.EvColor, this.LocalPlayer.WriteEvColor(), this.SendReliable, new RaiseEventOptions() { CachingOption = EventCaching.AddToRoomCache }); } }
OpRaiseEvent参数包括:
- byte eventCode事件代码指定要提出的实际事件。 有从由255开始向下计算的Photon的预定义事件。而从1开始到199,你可以定义在游戏逻辑中使用自己的事件。
- Hashtable evData您可以填写此哈希表来传输您需要的所有数据。 这是您将用于在客户端之间交换信息的中央数据结构。 但是,您游戏逻辑的标准的循环和标准化步骤应该作为事件发送(例如回合结束)。
- bool sendReliable当将此标志设置为“true”时,将从UDP切换到可靠的UDP(reliable UDP)。 这意味着在传输期间丢失的任何包将被重新发送,并且客户端将确保包将按照它们被发送的顺序被解释。 这可能会以负面的方式影响性能,因为这些额外的步骤将增加额外的消息量并增加整体通讯的数据负担。
- byte RaiseEventOptions.channelId您可以使用不同的通道对发送的事件进行分组和优先级排序。 我们将在一个小例子中说明此功能:假设您使用渠道1发送有关玩家位置的相关信息。 你在你的游戏中启用了可靠的UDP,因为你需要在你的游戏类型获得额外的可靠性。在某些时候,通道1会由于许多消息而拥挤,因为一些玩家有延迟,因为网络连接不好而产生了一定数量的通讯包丢失,因此必须重新发送许多消息。 而这时需要入列发送另一个重要事件(如本轮结束),可能需要一些时间才能确认,因为客户端仍然忙于接收来自通道1的所有位置更新。因此,如果您现在分派一个事件到channelId 0,它将优先于所有其他排队的消息处理。 通过合理的使用此功能,您可以获得设计预期的反应性,并确保游戏逻辑的正确执行,即使在一个平庸的的连接条件下。
- int [] RaiseEventOptions.targetActors要发送事件的房间中的ActorNumbers的列表。
- EventCaching RaiseEventOptions.CachingOption影响服务器如何处理事件缓存。 可以缓存玩家稍后加入的事件或删除以前缓存的事件。
最后但并非最终的方法,Photon还有额外的重载(Overload),你可以用来指定接收器组。
想进一步了解PhotonCloud光子云?
我们推荐您学习Exit Games的官方实例教学马可波罗,您可以在光子实践资源找到被翻译为中文的教程实践连接。
请留意,如果您有自己的服务器(VPS,阿里云等),那么PhotonServer光子服务器同样可以担负PhotonCloud光子云的服务器连接功能,请参照这篇文章和光子服务器的详细介绍。