返回开发者新闻

打造多人游戏 VR 体验:使用 Unity SharedSpaces 示例制作一款简单的多人游戏 VR 应用

2022年6月28日发布者:Navyata Bawa

“打造多人游戏 VR 体验”博客和视频专题系列共四部分,在这个系列中,我们将探索使用 Unity 制作的开源 SharedSpaces 示例,讨论开放平台 SDK 中与 Quest 多人游戏功能相关的内容,并介绍如何使用此示例构建自己的多人游戏应用程序。这是第 3 部分。如果错过第 2 部分,您可以阅读此处的博文,并观看此处的视频。

如果您有兴趣观看或收听此专题内容,请前往 Meta Open Source YouTube 频道,观看本视频

在今天的博文中,我们将讨论根据 SharedSpaces Unity 示例制作一款简单游戏的步骤。您将了解使用此示例如何能够简化多人游戏 VR 应用程序的原型建立和构建流程,并且无需自行设置所有功能。此方法可以帮您节省时间,让您专注于设计和游戏玩法,消除底层技术的后顾之忧。在本系列第 2 部分中,我们使用 Unity 制作了一个示例项目,下面我们将在此基础上进行构建。如果您错过这部分内容并且需要赶上进度,请查看博文视频

在您的 Unity 示例项目中,在 Assets 中创建一个名为“GameAssets”的空文件夹,您可以在此为本游戏所需的所有资产创建相应文件夹。所有游戏脚本都将保存在 SharedSpaces Scripts 主目录下一个名为“GameScripts”的文件夹中。

了解启动场景

SharedSpaces 示例的第一部分是启动场景,即创建在整个体验中可能需要的游戏对象和 prefab。此场景会带您进入大厅,您可以选择在此停留,也可以选择进入另一个虚拟房间。在开始创建自定义虚拟房间之前,请打开启动场景,了解游戏对象和脚本。

在此场景中,您会看到一些主要对象:

  • SharedSpacesApplication:此游戏对象包含 SharedSpaces 应用程序脚本,其中包含对网络层、场景加载程序、Spawner 和 VoIP 的引用。此脚本包含多种回调方法,用于建立、断开或恢复主机或客户端连接;还包含可供调用通过邀请面板发送邀请、记录错误、加入和加载正确虚拟房间等函数的方法。

  • SharedSpacesNetworkLayer:此游戏对象包含对 Photon Realtime 传输脚本的引用。此对象可充当网络管理工具,支持共享空间的玩家与网络层之间进行通信。网络管理工具脚本是一个 Unity netcode 脚本,可以处理所有网络相关设置,例如允许您开启或关闭网络、让您提供联网 prefab,以及注册场景名称。在 SharedSpaces 示例中,我们提供了对玩家 prefab 和下述会话的引用。

  • SharedSpacesSpawner:此对象包含 ShareSpacesSpawner 脚本,其中有生成网络 prefab 的方法。这些方法可返回 NetworkObject,如果您想让 prefab 在网络上永久存在,则需要添加此必要组件。我们稍后会详细讨论这部分内容。

创建布景

为了便于演示,我们将使用公共的紫色虚拟房间,但您可以在自己喜欢的任何虚拟房间执行此操作,也可以根据游戏需求进行更改。请注意,其他虚拟房间均为私人虚拟房间,需要您邀请好友。

现在,您已对启动场景中的部分方法有了基本了解,是时候进入下一场景了。由于您要在紫色虚拟房间内创建此游戏,所以在 Unity Assets 中打开“紫色虚拟房间”场景。您将看到部分元素已设置完毕。使用此设置构建您的世界。

在本示例中,您可以使用 Unity 的 Asset Store 取得所有游戏资产。您可以通过下方内容找到本游戏中使用的所有免费资产:

请注意,使用这些资产时应遵守相应的许可条款。请访问 Unity Asset Store,阅读上述链接中每项资产的详细许可条款。

深入探究这些资产之前,我们先了解一下这款游戏。在本示例中,您的游戏是一款双人游戏,两名玩家将在森林中比赛捕捉逃出后四处游荡的小鸡。第一个捕捉到 30 只小鸡的玩家获胜。通过这个简单的游戏,您将了解如何使用 SharedSpaces 示例来轻松制作多人游戏。我们将探讨 netcode 基础知识、如何邀请好友一起玩,以及多人游戏功能的其他方面。

回到您的场景中,导入以下资产作为 prefab:小鸡、农民和布景所需资产。首先,如图所示,将布景 prefab 拖入您的场景中。您的布景是一个低多边形森林场景。

接下来,添加您想生成小鸡的位置,让它们可以在该区域内自由移动。要执行此操作,请制作一个布景子对象,并命名为“Positions”。此子对象将包含您想生成小鸡的所有位置。

若要控制生成过程和常规游戏计分,请添加一个名为 GameController 的游戏对象,并为其附加 GameController 脚本。这将是您的主控制器,其中添加与小鸡实例化相关的逻辑。

GameController 脚本包含多种功能,如控制小鸡、小鸡生成位置、启用及禁用触发因素和重生点、显示赢家并在捕捉到小鸡时播放独特声效的逻辑。

接下来,您希望在游戏控制器中设定的任意位置将小鸡实例化。为此,添加一个名为 PopulateChickens 的协同程序,来控制小鸡实例化的位置和频率。若要让实例化后的小鸡可以自由移动,请向小鸡 prefab 添加一个脚本,将其命名为 RandomMovement。此脚本可让小鸡朝区域内的任意位置移动,并且可以控制它们的动画效果。为您的小鸡添加一个名为“Chicken”的标签,以便识别。确保小鸡的 prefab 附加有碰撞属性,并已启用“IsTrigger”标记。

返回到您的场景,添加可在捕捉到小鸡时触发的音频来源。添加两种声效:第一种在 GameController 上添加,可以在捕捉到小鸡时触发“Collect”声音;另一种在 SfxAmbience 上添加,作为“Background”声音。

现在,您已为玩家设置好基本场景。接下来,我们将设置您的玩家。

设置您的玩家 prefab

在您的游戏中,主要玩家是农民 prefab。打开 SharedSpacesPlayer prefab,并检查其中包含的元素,之后,您将充分了解玩家对象所需的组件,以及如何对其进行自定义才能使用您的玩家 prefab。

您将在玩家 prefab 中看到的部分组件如下:

  • NetworkObject:您希望玩家 prefab 在网络上永久存在,因此需要向其附加网络对象组件。

  • SharedSpacesPlayerColor:此组件将用于通过网络更新各个玩家的颜色。

  • SharedSpacesPlayerName:添加此组件的目的是在人物网格上方显示玩家的名称。

若要更新此 prefab,以便它能使用您的农民模型,请首先更新 Animator 下方的 Avatar,以使用您的农民网格。接下来,在 Geometry 选项卡下添加农民网格,而非使用默认的 Armature_Mesh。请务必在 SharedSpacesPlayerColor 脚本下更新 Mesh Renderer 的引用,以便与玩家的衬衫匹配。现在,玩家的 prefab 已准备就绪,可在场景中引用。您可以替换现有 prefab,或选择将其另存为新 prefab。

现在,您的玩家 prefab 已经就绪,此时可以更新引用,将您的农民实例化为玩家。

为此,请打开启动场景,选择 SharedSpacesNetworkLayer。此时,您需确保网络 prefab 引用的是 NetworkManager 脚本中的农民模型。

在 SharedSpacesSpawner 脚本下更新引用,以反映此 prefab。

另请确保所有 SharedSpaces Launch Triggers 会检查“Chicken”标签,且不会在游戏对象为小鸡时被触发。可以通过添加此项检查来完成此操作:

if (other.tag == "Chicken") return;

现在,当您启动示例时,您的玩家就会更新为农民。如果您进入紫色虚拟房间,就会看到小鸡正在生成。下一步是添加一些游戏和网络逻辑。

添加网络逻辑

您希望对游戏进行配置,以便当一名玩家捕捉到一只小鸡时,得分可以通过网络正确传播,并且两名玩家均可看到。为达到此目的,您需要使用 Unity Netcode 的网络变量和远程过程调用 (RPC)。如需深入了解 NetworkVariable,请查看 Unity NetworkVariable 文档。如需深入了解 RPC,请查看 Unity Netcode RPC 文档

系统会定期将 NetworkVariable 的值复制到网络中的其他节点。当某个客户端首次连接到某个主机时,NetworkVariable 的最新值将被复制到该新客户端上。在 SharedSpaces 中,添加 NetworkVariables 的逻辑属于 SharedSpacesPlayerState 类。请注意,此脚本从 NetworkBehaviour扩展而来,这是衍生自 MonoBehaviour 的抽象类,也是一个基本类,所有联网脚本都应从其衍生而来。

在此脚本中添加两个新的 NetworkVariables,一个用于显示第一名玩家的得分,另一个用于显示第二名玩家的得分。

public NetworkVariable<int> firstPlayerScore = new NetworkVariable<int>(); public NetworkVariable<int> secondPlayerScore = new NetworkVariable<int>();

指定第一位进入游戏中紫色虚拟房间的用户为玩家 1。接下来,创建一个可在每次捕捉到小鸡时调用的方法,并将其命名为 SetScore。

public void SetScore() { if (!LocalPlayerState) return; if (IsServer) { Debug.Log("First Player value changed");FirstPlayerCatchChickenServerRpc(); } else { Debug.Log("Second Player value changed");SecondPlayerCatchChickenServerRpc(); } }

在此方法中,您可以使用 RPC,根据是服务器还是客户端,来更新第一名玩家或第二位玩家的得分。如下所示,为其添加两个服务器 RPC。如需深入了解服务器 RPC,请查看 Unity Netcode Server RPC 文档

[ServerRpc] private void FirstPlayerCatchChickenServerRpc() { firstPlayerScore.Value++; } [ServerRpc] private void SecondPlayerCatchChickenServerRpc() { secondPlayerScore.Value++; }

现在您已完成这些设置,请确保您在玩家捕捉到小鸡时调用 SetScore 方法。为了检测玩家与小鸡之间的碰撞,请添加一个名为 DetectCollision 的新脚本,并将其附加到您的农民玩家。此脚本将在玩家捕捉到小鸡时调用 SetScore 方法。类似于:

private void OnTriggerEnter(Collider other) { if (other.gameObject.tag == "Chicken") { Destroy(other.gameObject);GameController.chickenCollected = true; playerState.SetScore(); } }
        

设置得分榜

您已设置好玩家、小鸡和网络代码,现在需要设置一个位置来展示得分情况和赢家。您还希望两名玩家可以同时查看得分。

在紫色虚拟房间内添加两个得分榜,一个用于玩家 1,另一个用于玩家 2。然后添加第三个得分榜,用来展示胜负状态。由于无需通过网络向第三个得分榜发送任何值或对其进行更新,所以请将它作为一个普通的游戏对象添加到您的场景中。下面的示例展示的是 Unity Asset Store 中的免费资产,可用于创建低多边形得分榜。

与您的玩家一样,这两个得分榜也需要通过网络更新。这两个得分榜应附加有 NetworkObject 组件,如下所示。

现在,确保 Spawner 在主机连接时生成新建的得分榜,同时确保得分榜只有在玩家进入紫色虚拟房间后方能显示。为实现此目的,请向您的得分榜添加引用,并在 SharedSpacesSpawner 脚本中添加两个新的生成方法,然后通过 SharedSpacesApplication 脚本调用这些方法:

SharedSpacesSpawner:

public NetworkObject firstPlayerScorePrefab; public NetworkObject secondPlayerScorePrefab; public NetworkObject SpawnFirstPlayerScoreBoard() { NetworkObject score = Instantiate(firstPlayerScorePrefab); score.Spawn(); return score; } public NetworkObject SpawnSecondPlayerScoreBoard() { NetworkObject score = Instantiate(secondPlayerScorePrefab); score.Spawn(); return score; }

SharedSpacesApplication:

public NetworkObject scoreBoardFirstPlayer; public NetworkObject scoreBoardSecondPlayer; private void OnHostStarted() { … scoreBoardFirstPlayer = spawner.SpawnFirstPlayerScoreBoard(); scoreBoardSecondPlayer = spawner.SpawnSecondPlayerScoreBoard(); } private void OnHostRestored() { … scoreBoardFirstPlayer = spawner.SpawnFirstPlayerScoreBoard(); scoreBoardSecondPlayer = spawner.SpawnSecondPlayerScoreBoard(); }
        

在 Spawner 和应用程序脚本中更新引用,然后将这些新的得分 prefab 添加到 NetworkManager 中的网络 Prefab 列表中。

设置得分榜的最后一步是在捕捉到小鸡时启用得分更新功能。为此,请添加两个脚本,每个得分榜一个。这些脚本可根据 SharedspacesPlayerState 脚本中的适当回调提供最新得分。

ScoreControllers:

ScoreControllerFirstPlayer 和 ScoreControllerSecondPlayer 这两个新脚本可以控制得分的更新方式,以及在得分榜上的显示方式。以下方法显示的是第一名玩家的得分发生变化时调用的函数:

public static void UpdateScore(int newScore) { firstPlayerCurrentScore = newScore; }

SharedSpacesPlayerState:

请务必添加 OnValueChanged 订阅,以便在得分发生变化时通知得分榜,进而更新得分榜。

OnEnable:

firstPlayerScore.OnValueChanged += OnFirstPlayerScoreChanged; secondPlayerScore.OnValueChanged += OnSecondPlayerScoreChanged;

OnDisable:

firstPlayerScore.OnValueChanged -= OnFirstPlayerScoreChanged; secondPlayerScore.OnValueChanged -= OnSecondPlayerScoreChanged; private void OnFirstPlayerScoreChanged(int oldScore, int newScore) { ScoreControllerFirstPlayer.UpdateScore(newScore); } private void OnSecondPlayerScoreChanged(int oldScore, int newScore) { ScoreControllerSecondPlayer.UpdateScore(newScore);
        

最后设置:构建和运行游戏

最后,请返回您的 GameController,确保得分榜可以正确显示胜负状态。在此阶段,您还必须确保所有面板在游戏开始时均已禁用,并且只有当两名玩家都在竞技场时才会出现小鸡。

现在,您已经准备好构建游戏了。点击“构建”,请确认您已设置密钥库,并且开放平台已设置为 Android。APK 就绪后,使用 ODH 在 Quest 头戴设备中安装并运行 APK,具体步骤如上一篇博文所示。

这就是关于如何使用 Unity SharedSpaces 示例构建简单游戏的速览内容。您已经了解如何设置玩家,如何利用 NetworkVariable 和 RPC 来确保程序已在网络上复制您的数据,以及如何使用简单几步便在 Quest 中构建一款简单的 VR 多人游戏。如果有意了解此博文中展示的所有脚本的速览内容,您可以查看 YouTube 频道的详细视频。在下一篇博文中,我们将讨论其他多人游戏功能,并了解传送可靠性、最佳实践、要点和资源。

请务必查看“打造多人游戏 VR 体验”系列中的上一篇博文,进一步了解其他多人游戏功能、您可以使用这些功能构建哪些应用,以及如何使用 SharedSpaces 示例入门:


本系列简介

本系列将探索使用 Unity 制作的开源 SharedSpaces 示例,讨论开放平台 SDK 中与 Quest 多人游戏功能相关的内容。为“打造多人游戏 VR 体验”系列视频提供支持的系列博客共四部分,本博客是第一部分。

如需了解有关开放平台 SDK 多人游戏功能以及 SharedSpaces 示例运行原理的更多信息,请参阅此Connect 环节,其中介绍了如何为 Quest 构建和开发多人游戏应用。要试用 Unity SharedSpaces 示例,请访问 App Lab,并在自己的头戴设备上运行此示例。如需了解有关如何在自己的应用中使用开放平台 SDK 多人游戏功能的更多信息,请参阅有关多人游戏功能的文档。

如需了解有关 Meta Quest 的更多信息,请访问我们的网站、订阅我们的 YouTube 频道,或在 TwitterFacebook 上关注我们。如果您有任何问题、建议或反馈,请在开发者论坛中告诉我们。

如需了解有关 Meta Open Source 的更多信息,请访问我们的 Open Source 网站、订阅我们的 YouTube 频道,或在 TwitterFacebook 上关注我们。