作为多人游戏的示例项目,《Boss Room》在一个可用于实际生产的环境中展示了各种 Unity 游戏服务的各项功能,供开发者学习多人游戏的开发。
Unity 游戏服务:
https://unity.com/cn/solutions/gaming-services
《Boss Room》有两个主要作用:
其一是作为一个示范性样例供社区用作项目基础,或作为零部件用在你自己的 Unity 游戏中。
其二,这也让我们有机会亲自尝试自己的解决方案——示例项目团队与 Unity 游戏服务团队携手合作,使用了他们的 SDK 来创建并维护一个具备所有常见功能的多人游戏。随着我们不断发布新的工具和功能,《Boss Room》也在不断发展、其功能也越来越多。
就在上个月,《Boss Room》更新了 v1.1.0-pre,为多人游戏服务端的开发者带来了一套全新的功能集。
请在下文详细了解《Boss Room》怎样整合 Unity 游戏服务并创造符合玩家期望的游戏房间功能。
让玩家联手勇闯《Boss Room》
作为一款多人游戏,《Boss Room》必须得有一个搜索和加入游戏的方式。
目前,玩家有两种方法来搜索并连接到游戏。
IP 直连允许玩家使用公开的 IP 地址相互连接。不过,一台电脑的网络通常要经由 NAT(网络地址转换设备)和路由器转接,因此直接连接到别人的电脑并没有想象得那么简单。
端口转发(Port forwarding)技术能让直连成为可能,但是主机方还是需要做一些额外设置才能让其他玩家连接。此种解决方案也不具备搜索游戏比赛的功能,玩家必须通过游戏外的信息分享渠道传递相关加入信息才行。而它的好处是可以使用局域网运行,不需要互联网连接。
端口转发(Port forwarding)技术:
https://docs-multiplayer.unity3d.com/docs/learn/listen-server-host-architecture#option-a-port-forwarding
像《Boss Room》这种多人游戏必须要能在互联网上游玩、游戏房间必须能被轻松搜索到,不可以强行让玩家自己完成端口转发。
那么这时 Unity 游戏服务就有用了——Authentication、Lobby 加 Relay 的组合技可以让玩家轻松地创建或加入联网游戏,不必再依靠端口转发或游戏外的协调。
在 Authentication、Lobby 和 Relay 服务整合到《Boss Room》之后,游戏的创建和加入会变得更加简单,让端口转发和分享游戏信息显得多余。
总的来说,游戏现在的联网体验更加顺畅和迅速,这一点对样例项目来说是加分项,对真正的游戏来说是必须项 。
接下来再来看看我们从项目制作中总结出来的经验吧!
《Boss Room》开发流程概览
从游戏体验来看,《Boss Room》是一个功能齐全、主机托管的 PVE 多人合作 RPG 游戏,支持最多 8 名玩家——详细的游戏功能和玩法可以通过以下链接了解。
https://blog.unity.com/games/enter-the-boss-room-our-new-multiplayer-sample-game
首先我们需要了解Authentication、Unity 游戏服务及本地迭代的流程。
玩家要想使用其他的 Unity 游戏服务,就必须经过身份验证,所以游戏在启动并加载完主菜单之后便会启动 Authentication。
Authentication 支持匿名登录,玩家不需要输入额外的信息即可开始游戏。
需要提一嘴的是,Authentication API 默认不会区分同一台设备的多个游戏实例,即便玩家打开了多个游戏进程,游戏登陆的仍是同一个账户。这点给本地的游戏测试带来了困难——ParrelSync 克隆出来的和实际的游戏都受到了影响。
幸而这里有一个简单的解决方案:Authentication 支持 Profiles 玩家档案,它正是解决问题的关键所在。Profiles 可以有效地让多名玩家同时在一台设备上进行游戏。要在本地进行测试,我们需要让正式版和编辑器版能在多个 Profile 间自由切换。
如果要创建玩家档案,你需要根据ProfileManager 类来决定使用哪一类 Profile。在正式版里我们使用的是`-AuthProfile`命令行参数来指定新档 ID。在编辑器中迭代时,我们用到了 ParrelSync,ProfileManager 类同样支持用 ParrelSync 的`Clone Manager`自定义参数来指定玩家档案的类型。
ProfileManager 类:
https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/develop/Assets/BossRoom/Scripts/Shared/ProfileManager.cs
我们还使用了`ProfileManager.Profile`来生成自定义的`InitializationOptions`。
var unityAuthenticationInitOptions = new InitializationOptions();var profile = ProfileManager.Profile;
if (profile.Length > 0)unityAuthenticationInitOptions.SetProfile(profile);执行档案切换和账户登入的逻辑代码如下:
async Task TrySignIn(InitializationOptions initializationOptions)await Unity.Services.Core.UnityServices.InitializeAsync(initializationOptions);
if (!AuthenticationService.Instance.IsSignedIn)await AuthenticationService.Instance.SignInAnonymouslyAsync();在上述任务完成后,我们就可以启动其他服务了,并且我们用了某种方法自动化了 ParrelSync 和 Profile 的本地迭代流程。我们最近在《Boss Room》中把这一点改为基于 dataPath,以减少对工具的束缚,但上述解决方案对 ParrelSync 用户仍然有效。
创建房间:建立主机的流程
玩家若想创建主机,可以输入游戏房间的名称、设定开放或加密房间,然后点击“create”按钮。
创建房间的API 这时就会被调用。新建的游戏房间会进入**locked**状态(区别于已经设置完毕并开放的游戏房间),直到系统成功完成下方分配中继网络和启动网码传输的步骤:
主机向 Relay 请求分配中继网络。
UTP 被启动,主机将进入角色选择场景房间解除锁定状态,让其他客户端可以自由加入。
加入游戏房间:客户端联网的流程
我们有几种加入游戏房间的方式:
连接到 Lobby 服务上托管的公开房间
快速加入(Quickjoin),随机加入一个公开房间
使用密码加入,密码可在游戏外分享。这些方式对公开和私人房间都适用。
在加入一个房间后,我们将使用房间元数据中所包含的中继网络入场码,通过UTP Relay 传输网络连接到主机。
主机将收到客户端的连接请求,如果一切顺利,玩家将依照服务器(主机)的权威跳入恰当的场景。
玩家创建或加入游戏之后
在建立连接后,玩家将进入角色选择场景,从八名英雄中选择一名。在所有玩家准备完毕后,每一位英雄会在倒计时结束后被传送至《Boss Room》世界,正式开始游戏。
注意,Unity 游戏服务 Lobby 和我们游戏中的“lobby”,也就是角色选择场景并不是一回事。《Boss Room》的角色选择场景由 netcode 驱动。
需要强调的是,Lobby 服务可以传输任意元数据,因此同样的角色选择场景完全可以应用到其他游戏中。
目前,Lobby 服务通过轮询(poll)来更新状态,这不利于提高选择角色时的响应性,如果 Lobby 服务在未来推出了可以实时更新的功能,那么该方法可以用作一种可行的备用方案。
断开连接和重新连接的处理
多人游戏的断线重连功能非常重要。
《Boss Room》使用的游戏进程管理系统可以在某位玩家断开连接时保留部分数据,在重新连上后再精确地传回去(详见SessionManager.cs - OnClientDisconnect)。
https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/develop/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/SessionManager.cs
我们使用的重连数据恢复方法可以在SessionManager.cs - SetupConnectingPlayerSessionData 中找到,该类会在主机处理连接批准时被调用(详见ServerGameNetPortal.s - ApprovalCheck)。
SessionManager.cs:
https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/develop/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/SessionManager.cs
ServerGameNetPortal.s:
https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/develop/Assets/BossRoom/Scripts/Shared/Net/ConnectionManagement/ServerGameNetPortal.cs
在房间内游戏时,断开连接的玩家最好能立即被移除。否则,服务器将一直认为玩家还在房间中,导致玩家无法重新加入。
当玩家断开了与 Relay 的连接时,Lobby 和 Relay集成系统(在运行UTP连接之前已经启用)会踢出断开连接的玩家,然而断开连接的状态会持续相当长时间(约为2分钟),因此我们不能仅依赖这种机制。
Lobby 和 Relay 集成系统:
https://docs.unity.com/lobby/relay-integrations.html
为了使退出房间的过程更加可靠,我们应用了几个额外的清理机制:
客户端包含有退出应用的逻辑(见ApplicationController.cs - OnWantToQuit and LeaveSession ),可以发送请求来将玩家移除
https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/develop/Assets/BossRoom/Scripts/Shared/ApplicationController.cs
主机有着专门的清理逻辑,如果有玩家断开连接,则主机就会把这名玩家从房间中移除(通过调用`NetworkManager.OnClientDisconnectCallback`)——这在客户端崩溃并且无法发送“退出房间”的请求时非常有用。为了做到这点,主机会用 SessionManager 来保存与 NGO clientId 对应的 UGS playerId。这个逻辑可以在 ServerGameNetPortal.cs - OnClientDisconnect 里找到(以下链接)。
https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/develop/Assets/BossRoom/Scripts/Shared/Net/ConnectionManagement/ServerGameNetPortal.cs
最后,客户端还包含了检测主机是否已离开房间的检测逻辑,如果主机离开了房间,则客户端也会离开。这方面的代码可以在 ClientGameNetPortal.cs - OnDisconnectOrTimeout 找到。
https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/develop/Assets/BossRoom/Scripts/Shared/Net/ConnectionManagement/ClientGameNetPortal.cs
欢迎持续关注
随着 Unity 游戏服务产品组和联网方案的不断发展和完善,《Boss Room》也将不断进步。你可以按以下方法持续关注:
关注《Boss Room》的GitHub 项目仓库。
《Boss Room》GitHub:
https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/releases/tag/v1.1.2-pre
关注 GitHub 上核心网码的开发进展,在公开路线图留下自己的更新或功能请求。
GitHub:
https://github.com/Unity-Technologies/com.unity.netcode.gameobjects
公开路线图:
https://unity.com/roadmap/unity-platform/multiplayer-networking
注册并探索Unity 游戏服务,关注我们的微信公账号
Unity 游戏服务:
https://unity.com/cn/solutions/gaming-services
Unity 官方微信
第一时间了解Unity引擎动向,学习最新开发技巧
每一个“在看”,都是我们前进的动力
热门跟贴