雨果·巴拉:行业北极星Vision Pro过度设计不适合产品市场

开发实战Part 3:为Quest 2构建多人游戏应用体验

查看引用/信息源请点击:映维网Nweon

构建多人游戏

映维网Nweon 2022年07月06日)多人游戏体验已经成为VR生态系统中越来越重要的一环。多人游戏功能允许你轻松地在各种游戏和应用中查找和邀请好友。

在这个“Building Your Multiplayer VR Experience(构建你的多人VR体验)”博文系列中,Meta将通过SharedSpaces示例来讨论Quest中的Platform SDK多人游戏功能,并向你展示如何利用所述示例来构建你的多人游戏应用。

延伸阅读开发实战Part 1:为Quest 2构建多人游戏应用体验
延伸阅读开发实战Part 2:为Quest 2构建多人游戏应用体验

在新一篇的博文中,Meta将介绍根据SharedSpaces Unity示例制作一个简单游戏的步骤。下面是映维网的具体整理:

在你的示例Unity项目中,创建一个名为“GameAssets”的空文件夹。你将用它来为游戏所需的所有asset创建文件夹。所有游戏脚本将位于主SharedSpaces Scripts之下的“GameScripts”文件夹。

1. 理解Startup场景

SharedSpaces示例从启动场景开始,并创建你在整个体验过程中可能需要的游戏对象和prefabs。然后是大厅,在这里你可以选择停留或进入另一个房间。在开始创建自定义房间之前,请打开Starup场景以熟悉游戏对象和脚本。

在这个场景中,你会注意到一定的主要对象:

  • SharedSpacesApplication:这个游戏对象包含SharedSpace应用脚本,它引用了网络层、场景加载程序、生成程序和VoIP。所述脚本由各种回调函数组成,用于建立、断开或恢复主机或客户端连接。它同时包括允许通过邀请面板发送邀请、记录错误、加入和加载正确房间等功能的函数。

  • SharedSpacesNetworkLayer:这个游戏对象引用了Photon Realtime传输脚本。它充当网络管理器,支持SharedSpaces的玩家和网络层之间的通信。网络管理器脚本是一个Unity netcode脚本,用于处理所有与networking相关的设置,例如允许你启动或停止networking,允许你提供网络预制和注册场景名称。在SharedSpaces示例中,团队提供了对玩家prefab和会话的参考,如下所示:

  • SharedSpacesSpawner:这个对象包含脚本SharespacesPawner,它具有生成网络prefab的函数。所述函数返回NetworkObject。

2. 创建你的环境

为了便于演示,本文使用的是公共Purple Room,但你可以在任何喜欢的任何房间中实现,并且可以根据游戏需要进行改动。请注意,其他房间属于私密,用于邀请朋友。

相信你现在已经对Startup场景中的函数有了基本的认知,所以下面我们是时候进入下一个场景。由于是在Purple Room中创建游戏,请从Unity Assets中打开Purple Room场景。你会看到已经设置了一定的元素。使用这一设置来构建世界。

在本例中,你可以将Unity的Asset Store作为所有game asset的来源地。下面提供了用于游戏的免费asset:

请注意,asset的使用应符合许可条款。

在深入了解asset之前,我们先了解更多关于游戏的信息。在这个示例中,构建的游戏将是一个双人游戏。其中,两名玩家竞争收集逃到森林的鸡。率先收集30只鸡的人获胜。通过这个简单的游戏,你将学习到如何使用SharedSpace示例轻松创建多人游戏。我们将讨论网络代码基础知识,邀请朋友一起玩,以及多人游戏功能的其他方面。

回到场景,导入以下asset作为prefab:鸡、农民和环境的asset。首先,将环境prefab拖到场景中。你的环境是低多边形森林场景。

接下来,添加生成鸡的目标位置,并令它们在区域内随机移动。为此,创建环境的子对象并将其称为“Positions”。这将包含生成鸡的所有位置。

要控制的鸡生成和游戏记分,请添加一个名为GameController的游戏对象,并附带GameController脚本。这将是你的主控制器,它添加了与鸡实例化相关的逻辑。

GameController脚本包含控制鸡的功能,鸡在哪里生成,启用和禁用触发器和生成点,显示谁获胜,以及在收集鸡时播放独特声音的逻辑。

接下来,你希望鸡在GameController设置的随机位置中实例化。为了实现这一点,添加一个名为PopulateChickens的协同程序,它控制鸡实例化的位置和频率。为了在鸡实例化后为其启用随机移动,请在鸡prefab中添加一个脚本,并将其称为RandomMovement。所述脚本令鸡向区域内的随机点移动,并控制其动画。给鸡加上一个名为“Chicken”的标签,这样你就可以识别它们。确保你的鸡有一个连接到prefab的collider,并启用“IsTrigger” flag。

回到场景,添加在收集鸡时触发的音频源。添加两个音效:一个GameController,当捕捉到鸡时触发“Collect”声音;另一个SfxAmbience,用于“Background”声音。

现在已经有了基本的场景设置。接下来,我们来看看如何设置你的玩家。

3. 设置玩家prefab

在游戏中,主玩家是一个农民prefab。打开SharedSpacesPlayer pfrefab并检查其包含的元素。然后你就会了解玩家对象需要什么组件,以及如何自定义它。

在玩家prefab中,你会注意到一定的组件:

  • NetworkObject:由于你希望玩家prefab在网络持久化,因此需要将网络对象组件附加到它。

  • SharedSpacesPlayerColor:用于通过网络更新玩家的颜色。

  • SharedSpacesPlayerName:添加它是为了在角色网格显示玩家的名称。

要更新这个prefab以使用农民模型,请首先更新Animatorx下的Avatar以使用农民网格。接下来,在 Geometry选项卡下添加农民网格。确保在SharedSpacesPlayerColor脚本下更新Mesh Renderer的参考,从而匹配玩家的衣服。现在,玩家prefab已准备好在场景中引用。你可以替换现有prefab,也可以选择将其另存为新prefab。

现在你的玩家prefab已经准备好,下面是时候更新引用来实例化你的农民,并将其作为玩家操纵的对象。

为此,请打开Startup场景并选择SharedSpacesNetworkLayer。在这里,你将确保网络prefab在NetworkManager脚本中引用农民模型。

更新SharedSpacesSpawner脚本下的引用以反映这一prefab。

你同时要确保所有SharedSpaces Launch Triggers检查“Chicken” flag,并且如果游戏对象是鸡时不会触发。这可以通过添加这个检查来实现:

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

现在当启动示例时,你的播放器将更新为农民。如果你进入Purple Room,你会看到鸡正在生成。下一步是添加游戏和networking逻辑。

4. 添加networking逻辑

你需要将游戏成,当一名玩家收集鸡时,分数通过网络正确传播,并对两名玩家可见。为此,你需要使用Unity Netcode的Network VariablesRemote Procedure Calls (RPCs)

NetworkVariable的值定期复制到网络中的其他节点。当客户端最初连接到主机时,NetworkVariable的最新值将复制到新客户端。在SharedSpace中,用于添加NetworkVariable的逻辑位于SharedSpacesPlayerState类中。请注意,这个脚本是从NetworkBehavior扩展而来,NetworkBehavior是从MonoBehavior派生的抽象类,是所有网络脚本应派生的基类。

在这个脚本中,添加两个新的NetworkVariable,一个用于第一名玩家的分数,另一个用于第二明玩家的分数。

public NetworkVariable firstPlayerScore = new NetworkVariable();
public NetworkVariable secondPlayerScore = new NetworkVariable();

指定第一个进入游戏Purple Room的人作为玩家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。

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

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

设置好后,确保在玩家收集鸡时调用SetScore函数。要检测玩家和鸡之间的collision,请添加一个名为DetectCollision的新脚本,并将其附加到农民玩家。这个脚本在收集鸡时将调用SetScore函数。类似于:

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

5. 设置记分牌

现在已经设置好了玩家、鸡和网络代码,接下来你需要一个地方来显示分数以及获胜者是谁。你同时希望两名玩家能够同时查看分数。

在Purple Room中添加两个记分牌,一个用于玩家1,另一个用于玩家2。接下来,添加第三个记分牌用于显示获胜者的状态。由于第三个记分牌不需要通过网络发送或更新任何值,请将其作为普通游戏对象添加到场景中。下面的示例显示了Unity Asset Store中用于创建低多边形记分牌的可用asset。

就像你的玩家一样,这两个记分牌同样需要通过网络更新。两个记分牌都应该附接一个NetworkObject组件,如下所示。

现在,确保spawner在主机连接时生成新创建的记分牌,并且它们仅在玩家进入Purple Room时出现。要实现这一点,请添加对记分牌的引用,并在SharedSpacesSpawner脚本中添加两个新的spawn函数,同时从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);

6. 最终设置、构建和运行游戏

最后,回到GameController,确保记分牌正确显示谁是赢家。在这里,你同时必须确保在游戏开始时禁用所有面板,并且只有当两名玩家都在竞技场时才填充鸡。

现在,你已经准备好构建游戏。单击“Build”,确保已设置密钥库,并且平台已设置为Android。APK准备好后,使用ODH在Quest头显安装并运行,如上一篇博文所示。

这关于博文快速过了一遍如何使用Unity SharedSpace示例构建简单的游戏。你学习了如何设置玩家,如何使用NetworkVariables和RPC来确保数据在网络复制,以及如何只需数个步骤就可以构建一个简单的VR多人游戏。如有兴趣,你可以参阅YouTube视频介绍。在下一篇博文中,Meta将介绍更多的多人游戏功能。

本文链接https://news.nweon.com/98744
转载须知:转载摘编需注明来源映维网并保留本文链接
素材版权:除额外说明,文章所用图片、视频均来自文章关联个人、企业实体等提供
QQ交流群苹果Vision  |  Meta Quest  |  微软HoloLens  |  AR/VR开发者  |  映维粉丝读者

您可能还喜欢...

资讯