Unity官方教程 联机部分翻译

Unity联机教程翻译
摘要由CSDN通过智能技术生成

(1)一个简单的联机示例

多人联机一直是一项细节性强且复杂的工作,包含很多细粒度的问题,比如如何让位于世界各地的各类设备实现数据同步以及交流。通过Unity的内嵌的多人联机系统以及HLAPI(High Level API),我们希望能够为这个问题提供一个简单的解决方案。
通过这个简单的联机示例,我们会展示如何从零开始,使用最简单的脚本和资源搭建一个多人联机项目。我们希望你能够在读完这篇文档之后,能够迅速掌握我们的多人联机系统与HLAPI的使用方法。
这篇文档会手把手地展示如何使用Unity内嵌的多人联机系统和HLAPI搭建一个多人联机项目。我们设计的每一步不仅泛用性强,而且包含许多关于多人联机的重要概念。开发者能够根据自己的需要扩展这些步骤以适应不同类型的游戏。当项目开发完毕后,它将能够支持两名玩家在两个不同的项目实例上独立地控制自己的角色,服务器会负责角色行为的控制和同步。玩家之间能够互相射击,也可以射击其他敌人。当玩家被击败时,他控制的游戏角色会复位。
这篇文档适合中级开发者阅读。我们希望开发者能够能够先阅读一下我们的多人联机开发手册,特别是Networking Overview部分以及The High Level API以及它们的子页,包括Network System Concepts
开始之前,请先:
- 创建一个空的Unity3D项目。
- 将默认的scene保存为”Main”。

Unity网络功能概览(Networking Overview)

使用联网特性的开发者大致可以分为两类:
- 使用Unity开发联机游戏的开发者。这类开发者应当首先阅读NetworkManager部分或是High Level API部分。
- 搭建网络基础部分以及开发高级联机游戏的开发者。这类开发者应当首先阅读NetworkTransport API部分。

高级脚本API(High level scripting API)

Unity的联网系统有一组高级脚本API(HLAPI)。这些方法基本上能覆盖绝大部分的多人游戏的共同需求。使用这些API,你可以忽略底层细节,专注于功能的开发。简单来讲,这些API能够:
- 使用NetworkManager控制游戏的连接状态。
- 管理”客户端主机”游戏,这类游戏中的主机由一个玩家客户端扮演。
- 使用一个多功能的serializer序列化数据。
- 发送以及接收网络消息。
- 从客户端向服务器端发送指令。
- 实现客户端到服务器端的远程过程调用(RPC)。
- 从客户端向服务器端发送网络事件。

与编辑器和引擎的结合

Unity的网络系统嵌入到了它的编辑器和引擎中,这让网络游戏的开发变得可视化。它提供了:
- NetworkIdentity,用于需要联网的组件。
- NetworkBehaviour,用于联机脚本。
- 可配置的对象变化自动同步。
- 脚本变量自动同步。
- 在Unity Scene中放置网络构件。
- Network components

网络服务

Unity提供了网络服务来为你的游戏开发提供便利,包括以下功能:
- 比赛匹配。
- 创建比赛以及通告比赛。
- 显示可用的比赛以及加入。
- 中继服务器(Relay Server)。
- 无服务器的联网对局。
- 向比赛参与者发送消息。

网络传输以及实时传输层(real-time transport layer)

Unity提供了实时传输层(real-time transport layer),提供了:
- 最优化的基于UDP的传输协议。
- 多通道设计,用于避免队头消息阻塞。
- 支持设置每个通道的服务质量(QoS)。
- 灵活的网络拓扑结构,支持端到端以及客户端-服务器结构。

示例项目

这里可以找到示例项目:https://forum.unity.com/threads/unet-sample-projects.331978/?_ga=2.37697120.1374918886.1508243698-263594280.1507883404
包括:
- 多人2D坦克对战游戏。
- 多人战争游戏,支持比赛匹配。
- 多人太空射击游戏,支持比赛匹配。
- 最简单的多人联机项目。

(2)网络管理器(Network Manager)

这节课中,我们将创建一个新的Network Manager对象。这个Network Manager对象会控制这个多人联机项目的状态信息,包括游戏状态管理,场景管理,比赛创建,并且支持访问Debug信息。高级开发者还能够扩展NetworkManager类来自定义组件的行为,不过这部分内容不会包含在这节课中。
想要创建一个新的Network Manager对象,我们需要创建一个新的GameObject,并为其加上NetworkManager与NetworkManagerHUD组件(Component):
- 创建一个空的Object;
- 将其重命名为”Network Manager”;
- 选中这个Object;
- 添加组件(Add Component):Network > NetworkManager;
- 添加组件(Add Component):Network > NetworkManagerHUD;

NetworkManager组件会管理游戏的联网状态。
Network Manager
NetworkManagerHUD组件和NetworkManager协同工作,并提供了一个简单的用户接口来控制游戏在运行时的联网状态。
NetworkManagerHUD
在运行时,NetworkManagerHUD看起来会像是这样:

这里可以找到更多细节:https://docs.unity3d.com/Manual/UNetManager.html?_ga=2.40090082.1374918886.1508243698-263594280.1507883404

(3)建立Player预制件(Prefab)

在这个项目中,player预制件用于代表玩家们。
默认情况下,NetworkManager会通过克隆player预制件并生成到游戏中来为每个连接进游戏的玩家实例化一个游戏对象。
网络生成(Network Spawning)以及在客户端和服务器上同步游戏对象的细节会在后面的课程中介绍。
这里,玩家的GameObject会是一个简单的胶囊体,上面附着一个”脸”,用来告诉我们这个胶囊体的朝向。
完成后的GameObject会是这样:

要创建这个GameObject,你需要:
- 创建一个Capsule。
- 将其重命名为”Player”。

为了指示出这个对象的“前方”,为它添加一个子立方体,并将颜色设置为黑色:
- 选中Player。
- 创建一个立方体,并将其设置为Player的子物体。
- 将其重命名为”Visor”。
- 设置它的Scale为(0.95, 0.25, 0.5)。
- 设置它的Position为 (0.0, 0.5, 0.24)。
- 创建一个新的Material。
- 将其重命名为”Black”。
- 选中Black。
- 将它的Albedo color改为黑色。
- 将Visor的Material设置为Black。简单的方法是直接把Material拖到Scene视图的Visor上。

为了将Player标识为一个特殊的联网的游戏对象,为Player添加一个NetworkIdentity组件:
- 选中Player。
- 添加组件(Add Component):Network > NetworkIdentity。

NetworkIdentity组件用来在网络上识别这个物体,并让网络系统意识到它。
- 将 Local Player Authority 设置为true。


将Player的NetworkIdentity设置为Local Player Authority会允许客户端控制Player的移动。
接下来由Player创建一个预制件:
- 把Player从Hierarchy视图拖到Project视图来创建一个新的prefab资源。
- 从场景中删除Player。
- 保存场景。

(4)注册Player预制件

当Player预制件创建完毕后,我们需要对其进行注册。Network Manager会用这个预制件】来生成新的玩家控制的对象,并置入场景中。
- 在Hierarchy视图中选中之前创建的Network Manager。
- 在Inspector视图中打开Spawn Info标签。
- 把Player预制件拖进Player Prefab域中。


NetworkManager组件被用来控制联机对象的生成,包括Player。在许多游戏中,玩家都会有一个归自己控制的标志性的对象。NetworkManager有一个专门的域,用来存放用于代表玩家的Player预制件。每个进入游戏的玩家客户端都会得到一个新创建的游戏对象

(5)让Player动起来

接下来我们会制作游戏的第一个功能特性:在场景中移动Player。为此,我们会编写一个新的脚本,叫做“PlayerController”。
首先编写最简单的代码部分,这部分不会涉及到联网功能,仅仅在单一玩家环境下工作。
- 为Player预制件(prefab)创建一个新的脚本,命名为”PlayerController”。
- 打开脚本编辑器。
- 写入如下代码:

    using UnityEngine;

    public class PlayerController : MonoBehaviour
    {
        void Update()
        {
            var x = Input.GetAxis("Horizontal") * Time.deltaTime * 150.0f;
            var z = Input.GetAxis("Vertical") * Time.deltaTime * 3.0f;

            transform.Rotate(0, x, 0);
            transform.Translate(0, 0, z);
        }
    }

这个简单的脚本能实现移动人物与转向的功能。默认情况下Input.GetAxis("Horizontal")Input.GetAxis("Vertical")允许玩家通过WASD与方向键乃至触摸面板来控制玩家。如果想要改变键位,请查询Input Manager相关内容(Edit-Project Settings-Input)。
接下来:
- 保存脚本。
- 回到Unity。
- 保存场景。

(6)对Player进行在线测试

以Host的身份进行测试

现在,Player还只能够在客户端上移动,没有联网功能。
想要进行联网测试:
- 进入Play模式。

在Play模式中,NetworkManagerHUD默认显示如下:

- 单击LAN Host按钮,这能够让你以主机的身份启动游戏。

NetworkManager会用Player预制件创建一个新的Player,NetworkManagerHUD会改变显示来表明服务器目前处于活动状态。
这种情况下,游戏以”Host”模式运行。服务器和客户端处于同一个进程中。
接下来:
- 用WASD来控制Player。
- 单击Stop按钮来断开连接。
- 退出Player模式。

以客户端的身份进行测试

想要以客户端的身份进行测试,我们需要两个同时运行的游戏实例,其中一个扮演Host。一个可以从编辑器中打开,而另一个就必须首先Build项目之后才能打开。因此,如果我们想在客户端上测试游戏,就必须Build这个项目。
- File-Build Settings。
- 加入场景Main。
- 点击Build and run。
- 启动时选择一个较小的分辨率,保证能够同时看到编辑器。

游戏启动(后面称这个实例为Instance)后,你应该能看到NetworkManagerHUD面板。
- 点击Host按钮,这样Instance会扮演Host。

这时你应该能看到一个Player。试着用WASD控制它。之后:
- 返回Unity。
- 进入Play模式。
- 点击LAN Client按钮来扮演客户端,并和Host建立连接。
- 试着用WASD控制它。

你会发现两个Player都在移动。这时:
- 回到Instance。

你应该还会发现,在Editor中两个Player的位置和Instance中不同。这是因为PlayerController脚本现在还没有联网功能。当前,两个Player上都附着同样的脚本。在两个不同的实例中,这两个脚本都在处理同样的输入信息。Host和Client彼此都能意识到对方的存在,NetworkManager也为它们分别创建了两个不同的Player,但是Player对象没有和Host进行交流,因此NetworkManager无法追踪它的位置,简单来说就是没有同步。
接下来:
- 关掉Instance。
- 回到Unity。
- 退出Play模式。

(7)让Player的移动在线化。

为了给Player的移动赋予在线特性,并保证每个玩家只能控制它们自己的Player,我们需要更新PlayerController脚本。我们需要给脚本做两个大的改动:使用UnityEngine.Networking命名空间,以及让PlayerController继承自NetworkBehaviour,而不是MonoBehaviour。
- 打开PlayerController脚本。
- 添加UnityEngine.Networking命名空间。using UnityEngine.Networking;
- 将MonoBehaviour改成NetworkBehaviour。public class PlayerController : NetworkBehaviour

接下来加入一段代码,用于检查是不是本地对象,这样就能保证只有玩家只能控制对应的Player。

    if (!isLocalPlayer)
    {
        return;
    }

下面是完整的脚本:

    using UnityEngine;
    using UnityEngine.Networking;

    public class PlayerController : NetworkBehaviour
    {
        void Update()
        {
            if (!isLocalPlayer)
            {
                return;
            }

            var x = Input.GetAxis("Horizontal") * Time.deltaTime * 150.0f;
            var z = Input.GetAxis("Vertical") * Time.deltaTime * 3.0f;

            transform.Rotate(0, x, 0);
            transform.Translate(0, 0, z);
        }
    }

UnityEngine.Networking命名空间包含了编写具有联网功能的脚本所需的内容。
NetworkBehaviour是一个基于Monobehaviour的特别的类。所有自定义的,使用联网特性的脚本都继承自它。
注意到isLocalPlayer。LocalPlayer是NetworkBehaviour的一部分,所有继承自NetworkBehaviour的脚本都能够理解它的含义。想要理解LocalPlayer是什么,以及它是如何工作的的话,需要查阅关于HLAPI的文档。
在一个联机项目中,无论是服务器还是客户端,执行的代码都来自于同一个脚本,在上文中就是PlayerController脚本。假设有一个服务器端和两个客户端,那么就会有6个需要处理的游戏对象。这是因为玩家有两名,服务器端与两个客户端都会存在这两个玩家控制的游戏对象,2×3=6。

  • 4
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Unity是一款功能强大的游戏制作引擎,它可以用来制作各种类型的游戏,包括手游。在Unity中,联机功能是非常重要的一部分,因为联机可以将多个玩家连接到同一个游戏世界中,让游戏变得更加有趣和有挑战性。 首先,在Unity中实现联机功能需要使用网络编程的知识,因此,你需要理解TCP/IP协议、网络数据传输等相关内容。然后,你需要用Unity中的UNET(Unity Networking)组件来构建联机功能。UNET是Unity自带的一个网络组件,它可以让你轻松地将游戏中的玩家连接到同一个服务器上。使用UNET,你可以创建主机和客户端,主机会将游戏状态同步到它所有的客户端上。 接下来,你需要设置玩家角色的同步方式。玩家角色有多种同步方式,例如平滑插值、插值、预测、快照等。你需要根据你的游戏特点来选择适合的同步方式。 最后,你需要处理数据同步的问题。在联机游戏中,多个玩家需要同时看到同一状态。所以需要对游戏的状态进行同步,以保证所有玩家看到的游戏状态都是一致的。例如,当一个玩家移动时,需要将其位置同步到其他玩家的客户端上。 总的来说,在Unity中实现联机功能需要先理解网络编程的知识,然后利用UNET组件构建联机实现。最后,需要通过适当的同步方式和数据同步来保证游戏的玩法和状态一致性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值