Unity网络多玩家游戏开发教程.pdf
Unity 网络多玩家游戏 开发教程(上册)(内部资料)大学霸 前言 多玩家通过联网的方式共同进行的游戏被称为网络游戏。网络游戏由于具备更强的娱乐性和对战性成为游戏的主流。在这个互联互通的时代,多人联网玩同一个游戏,已经成为大众的习惯。Unity 作为强大的游戏开发平台,为网络游戏的的开发提供大量的组件和 API。同时,也涌现了大量的第三方的插件。网络游戏涉及网络构建、通信方式、数据带宽、数据逻辑同步等多方面问题。本教程针对这些热点问题,重点讲解 Unity 游戏开发中的常见技术、插件等。内容包括:Unity 自带网络组件 Network View(上册)第三方组件网络功能插件 PUN(上册)Yahoo 专向技术 Play.IO(上册)第三方 SDK PubNub(下册)实体差值和预测(下册)击中检测(下册)1.学习所需的系统和软件学习所需的系统和软件 安装 Windows 7 操作系统 安装 Unity 4.x 2.学习建议学习建议 大家学习之前,可以致信到 xxxxxxxxxx,获取相关的资料和软件。如果大家在学习过程遇到问题,也可以将问题发送到该邮箱。我们尽可能给大家解决。3.特别声明特别声明 因为篇幅有限,书中在讲解代码时很难细致到每行代码,如有疏漏可能会造成读者制作效果与书中所讲不一致的情况,本书附带源代码,此时应该以代码为准。目 录 第 1 章 Unity 自带网络功能实例:乒乓球游戏.1 1.1 实现机制.1 1.1.1 NetworkView 组件.1 1.1.2 自定义串行化数据.2 1.1.3 使用远程过程调用.2 1.2 默认服务器机制.4 1.2.1 初始化服务器.4 1.2.2 连接到服务器.5 1.3 自定义服务器机制.7 1.3.1 设置主服务器.8 1.3.2 连接到自定义的主服务器.11 1.4 注册“服务”.12 1.4.1 在主服务器上注册一个服务.13 1.4.2 在游戏视图上浏览特定服务.14 1.5 实例:乒乓球游戏.18 1.5.1 搭建游戏场景.18 1.5.2 游戏的功能逻辑.20 1.5.3 编写实现游戏逻辑的脚本.20 1.6 为游戏实例添加网络对战功能.28 1.6.1 初始化服务器.28 1.6.2 串行化球拍的移动状态.29 1.6.3 指定球拍出现的时机.31 1.6.4 串行化乒乓球的移动状态.33 1.6.5 游戏分数的网络化.36 1.6.6 加入游戏.39 1.6.7 网络对战功能演示.41 1.7 Unity 自带网络功能模型示意图.43 第 2 章 提供网络功能的 PUN 插件实例:聊天室.44 2.1 配置 PUN 环境.44 2.1.1 什么是 PUN.44 2.1.2 获取 PUN 插件.44 2.1.3 PUN 的核心Photon View 组件.47 2.2 使用 PUN.49 2.2.1 连接到 Photon Cloud,获取 Room 列表.49 2.2.2 创建 Room.51 2.2.3 加入 Room.53 2.3 聊天室实例使用的技术.53 2.3.1 筛选满足特定条件的 room.53 Unity 网络多玩家游戏开发教程(内部资料) 版权所有 II 2.3.2 随机加入一个 room.57 2.3.3 查看其它玩家的状态.59 2.3.4 同步所有玩家的游戏场景.60 2.3.5 效果展示.62 2.4 实例:聊天室.64 2.4.1 “上线”窗口.64 2.4.2 “大厅”窗口.66 2.4.3 “好友列表”窗口.68 2.4.4 “聊天”窗口.71 2.4.5 聊天室效果展示.73 第 3 章 专属的服务器技术 Player.IO实例:RTS 协议.76 3.1 Player.IO 概述.76 3.2 配置服务器Development Server.76 3.3 客户端的操作.81 3.3.1 使用 Unity Client SDK.81 3.3.2 连接到 Player.IO.82 3.3.3 获取 room 列表.83 3.3.4 连接到 room.85 3.3.5 创建 room.86 3.3.6 消息的发送与接收.92 3.4 配置 Development Server.95 3.5 数据库服务BigDB.99 3.5.1 写入数据.100 3.5.2 载入数据.102 3.6 实例:RTS 协议概述.103 3.7 RTS 协议服务器端.104 3.7.1 服务器端架构.104 3.7.2 服务器处理来自客户端的消息.107 3.7.3 服务器对其它事件的处理.112 3.8 RTS 协议客户端.114 3.8.1 MainMenu 场景.115 3.8.2 GameplayScene 场景.118 Unity 网络多玩家游戏开发教程(内部资料) 版权所有 2 第 1 章 Unity 自带网络功能实例:乒乓球游戏 Unity 拥有大量的第三方插件,专门提供了对网络功能的支持。但是,大部分开发者第一次接触到的还是 Unity 自带的网络功能,也就是大家经常说到的 Unity Networking API。这些 API 是借助于组件 NetworkView 发挥作用的,而它可以简化开发者大量的网络功能编码任务。1.1 实现机制 Unity 提供了名为 NetworkView 的组件,拥有此组件的对象才可以向网络传输、或者接收数据。本节会详解介绍此组件的各属性,及其向网络传输、接收数据的方法。图 1-1 所示,是本节要介绍的内容的示意图。游戏对象游戏NetworkView状态数据远程调用游戏对象游戏NetworkView状态数据远程调用网络 图 1-1 NetworkView 组件的用途 1.1.1 NetworkView 组件 在 Unity 中,NetworkView 组件用于处理游戏在网络上的数据传输,通常负责具体的游戏对象的状态数据串行化(state serialization)。例如,将游戏对象上 Transform、Rigidbody和 Animation 组件的数据串行化到网络上。为游戏对象添加 NetworkView 组件的方法是,单击 Component|Miscellaneous|Network View 命令,此组件如图 1-2 所示。图 1-2 NetworkView 组件 提示:此组件被添加到了游戏场景中默认创建的对象 Main Camera 上。Unity 网络多玩家游戏开发教程(内部资料) 版权所有 3 State Synchronization:表示要同步(串行化)的状态信息;提示:此属性有 3 个可选项。Off 表示不需要同步任何状态;Reliable Delta Compressed表示使用可信任的数据差异压缩传输方式,且只传输变化了的数据,若没有变化,那么就不会传输任何数据;Unreliable 表示要使用不信任的数据传输方式,每次都传输全部的数据,即时数据没有发生变化(需要占用更大的带宽)。Observed:表示要同步的信息的类型;提示:示例中要同步的信息的类型是 Transform 组件上的数据。ID:唯一的标识特定对象上的 Network view 组件;提示:多人网络游戏中,同一对象的此 ID 值是一致的。1.1.2 自定义串行化数据 上一节讲解了使用 NetworkView 组件指定串行化数据的方法。例如,数据类型是Transform 组件上的数据,就要为 NetworkView 组件上的 Observed 属性指定为特定对象上的Transform 组件。而本节就来说明在脚本中自定义串行化数据的方法,数据的类型同样是Transform 组件上的数据。在 Project 视图里,新建 C#脚本,命名为 ExampleUnityNetworkSerializePosition,并添加下面的代码:01 using UnityEngine;02 using System.Collections;03 04 public class ExampleUnityNetworkSerializePosition:MonoBehaviour 05 06 public void OnSerializeNetworkView(BitStream stream,NetworkMessageInfo info)07 08 /判断当前是否打算向网络上写入数据 09 if(stream.isWriting)10 11 /写入对象的位置信息 12 Vector3 position=transform.position;13 stream.Serialize(ref position);14 15 /当前正在从网络上读取数据 16 else 17 18 /将读取到的数据存储到 Vector3 类型的变量中 19 Vector3 position=Vector3.zero;20 stream.Serialize(ref position);21 /实时修改对象的位置 22 transform.position=position;23 24 25 脚本 06 行,OnSerializeNetworkView()方法会被 Unity 主动调用,用于串行化自定义的数据;BitStream 类表示串行化的数据,它有两个变量 IsReading 和 IsWriting,分别用于判断当前处于读取,还是写入状态;Unity 网络多玩家游戏开发教程(内部资料) 版权所有 4 BitStream 类依据当前的读取,或者写入状态,调用自己的 Serialize()方法从流中读取数据,或者写入数据到流中;1.1.3 使用远程过程调用 远程过程调用(RPC,Remote Procedure Calls)的作用是,为了达到多人游戏的同步效果,调用远程机器上,特定对象上的方法。例如,玩家自己的角色在当前的机器上发射了子弹,那么处于同一游戏中的其它玩家,也应该在它们的机器上,看到那个角色发射了子弹。本节就来说明在脚本中使用远程过程调用的方法。在 Project 视图里,新建 C#脚本,命名为 ExampleUnityNetworkCallRPC,并添加下面的代码:01 using UnityEngine;02 using System.Collections;03 04 public class ExampleUnityNetworkCallRPC:MonoBehaviour 05 06 void Update()07 08 /如果此 NetworkView 组件不属于此对象,就不做任何反应 09 if(!networkView.isMine)10 return;11 /当按下空格键的时候,调用所有同一游戏中,同一对象上的 testRPC 方法 12 if(Input.GetKeyDown(KeyCode.Space)13 networkView.RPC(testRPC,RPCMode.All);14 15 RPC 16 void testRPC(NetworkMessageInfo info)17 18 /记录调用此方法的电脑所在的 IP 地址 19 Debug.Log(Test RPC called from +info.sender.ipAddress);20 21 远程过程调用就是使用 networkView.RPC()方法,第一个参数表示要远程调用的方法名,第二个参数表示接收远程调用的主机;脚本 15 行的属性标记是必不可少的;提示:networkView.RPC()方法的第二个参数,有 5 个可选项,如图 1-3 所示,分别表示只发送给服务器、除发送者以外的所有主机、除发送者以外的所有主机并添加到缓存、所有主机,以及所有主机并添加到缓存。Unity 网络多玩家游戏开发教程(内部资料) 版权所有 5 图 1-3 networkView.RPC()方法第二个参数的可选项 1.2 默认服务器机制 游戏本身需要在网络上创建一个服务,然后其它游戏才能连接到这个服务,进而实现在同一游戏场景中一同玩耍的效果,如图 1-4 所示。玩家1Network.InitializeServer()初始化服务器Network.Connect()连接到服务器服务玩家2一同游戏的两位玩家一同游戏的两位玩家 图 1-4 默认服务器机制 1.2.1 初始化服务器 对于游戏本身而言,无论是玩家打算创建一个新的游戏也好,还是打算加入其中一个游戏也罢,游戏本身都必须先在本机上初始化服务器。在 Project 视图里,新建 C#脚本,命名为 ExampleUnityNetworkInitializeServer,并添加下面的代码:01 using UnityEngine;Unity 网络多玩家游戏开发教程(内部资料) 版权所有 6 02 using System.Collections;03 04 public class ExampleUnityNetworkInitializeServer:MonoBehaviour 05 06 void OnGUI()07 08 /在游戏视图上绘制一个按钮,当此按钮被单击的时候,开始启动服务器 09 if(GUILayout.Button(Launch Server)10 11 LaunchServer();12 13 14 /启动服务器 15 void LaunchServer()16 17 /接受来自 8 个主机的连接,监听的端口号是 25005,支持 NAT 穿透 18 Network.InitializeServer(8,25005,true);19 20 /Network.InitializeServer()调用完毕后,主动调用此方法 21 void OnServerInitialized()22 23 Debug.Log(Server initialized);24 25 脚本 18 行,方法 Network.InitializeServer()用于初始化服务器,需要传入 3 个参数:第一个参数表示允许连接到此服务器上的主机的数目;第二个参数表示要监听的端口号;第三个参数表示是否支持 NAT 穿透;脚本 21 行,方法 OnServerInitialized()会在 Network.InitializeServer()调用完毕后,被主动调用;将脚本 ExampleUnityNetworkInitializeServer 赋予游戏场景的 Main Camera 对象,然后运行游戏,效果如图 1-5 所示。当单击了游戏视图上的 Launch Server 按钮以后,完成服务器的初始化之后就会在 Console 视图上显示“Server initialized”信息。图 1-5 初始化服务器效果展示 1.2.2 连接到服务器 上一节使用脚本初始化了一个服务器,而本节会编写一个脚本,用于连接上一节创建的那个服务器,具体的操作步骤如下:Unity 网络多玩家游戏开发教程(内部资料) 版权所有 7(1)在 Project 视图里,新建 C#脚本,命名为 ExampleUnityNetworkingConnectToServer,并添加下面的代码:01 using UnityEngine;02 using System.Collections;03 04 public class ExampleUnityNetworkingConnectToServer:MonoBehaviour 05 06 private string ip=;07 private string port=;08 private string password=;09 void OnGUI()10 11 /在游戏视图上绘制 IP 地址输入区域 12 GUILayout.Label(IP Address);13 ip=GUILayout.TextField(ip,GUILayout.Width(200f);14 /在游戏视图上绘制端口号输入区域 15 GUILayout.Label(Port);16 port=GUILayout.TextField(port,GUILayout.Width(50f);17 /在游戏视图上绘制密码输入区域 18 GUILayout.Label(Password(optional);19 password=GUILayout.PasswordField(password,*,GUILayout.Width(200f);20 /当按钮被点击后,开始连接指定的服务器 21 if(GUILayout.Button(Connect)22 23 int portNum=25005;24 if(!int.TryParse(port,out portNum)25 26 Debug.LogWarning(Given port is not a number);27 28 /使用获取到的 IP 和端口号直接连接服务器 29 else 30 31 Network.Connect(ip,portNum,password);32 33 34 35 /连接到服务器以后,被 Unity 主动调用 36 void OnConnectedToServer()37 38 Debug.Log(Connected to server!);39 40 /连接服务器操作失败后,被 Unity 主动调用 41 void OnFailedToConnect(NetworkConnectionError error)42 43 Debug.Log(Failed to connect to server:+error.ToString();44 45 脚本 0608 行,分别声明了用于表示 IP 地址、端口号和密码的变量;脚本 0934 行,方法 OnGUI()用于在界面上绘制对应的 UI 控件,作为玩家输入指定信息的接口。脚本31行,方法Network.Connect()用于使用获取到的IP和端口号直接连接服务器;(2)上 一 节,我 们 为 游 戏 场 景 中 的Main Camera对 象,赋 予 了Unity 网络多玩家游戏开发教程(内部资料) 版权所有 8 ExampleUnityNetworkInitializeServer 脚本,作用是初始化服务器。现将其单独编译成可执行文件,方法是单击 File|Build Settings命令,在打开的 Build Settings 对话框中,添加当前的游戏场景到 Scenes In Build 列表区域,再单击 Build And Run 即可,如图 1-6 所示。图 1-6 Build Settings 对话框(3)第(2)步的操作,初始化并启动了一个服务器,它监听的端口号是 25005,没有任 何 密 码。回 到Unity 编 辑 器 中,选 中Main Camera对 象,移 除 其 上 的ExampleUnityNetworkInitializeServer(Script)组 件,然 后 赋 予 本 节 编 写 的 脚 本ExampleUnityNetworkingConnectToServer,并运行游戏,在游戏视图上输入 IP 地址和,端口号以后,就可以连接到那个服务器了,效果如图 1-7 所示。图 1-7 连接到服务器的效果展示 Unity 网络多玩家游戏开发教程(内部资料) 版权所有 9 1.3 自定义服务器机制 本章前面两节,涉及服务器的操作,都是使用了 Unity 默认指定的主服务器(Master Server)和通讯服务主体(Facilitator)来完成的。但在实际的开发中,建议读者使用自己的主服务器和通讯服务主体。本节就来说明,设置自己的主服务器的方法,如图 1-8 所示。玩家1Master ServerNetwork.InitializeServer()初始化服务器Network.Connect()连接到服务器服务玩家2一同游戏的两位玩家一同游戏的两位玩家Facilitator指定主服务器和通信服务主体指定主服务器和通信服务主体管理 图 1-8 自定义服务器机制 1.3.1 设置主服务器 Master Server 的作用是显示当前所有被初始化了的服务器,而 Facilitator 的作用是辅助各客户端连接彼此,使用的技术是 NAT 穿透(NAT punch-through)。在了解了这些以后,本小节接下来就要介绍设置主服务的方法了,如下:(1)输入网址:http:/ 1-9 所示的网页,下载 Unity提供的 Master Server 和 Facilitator 组件。Unity 网络多玩家游戏开发教程(内部资料) 版权所有 10 图 1-9 Unity Networking Servers 页面(2)下载到的两个压缩文件如图 1-10 所示。压缩文件内部是未编译的源码,包含了 3种类型的项目文件夹,如图 1-11 所示。读者应该依据当前所做开发时使用的操作系统环境,决定要编译哪一个项目文件。提示:详情请参看网址:http:/ 1-10 下载到的压缩文件 图 1-11 压缩文件中的 3 种项目文件夹(3)本书写作时,使用的操作系统平台是 Windows,因此需要编译的是 Visual Studio文件夹里的项目文件,使用的编译器是 Microsoft Visual C+2010 Express,此编译器是个免费的版本,下载网址是:http:/ 1-12 所示。Unity 网络多玩家游戏开发教程(内部资料) 版权所有 11 图 1-12 Microsoft Visual C+2010 Express 下载页面(4)使用 Release,而非 Debug 模式编译项目文件,最后得到的两个 EXE 文件如图 1-13所示。它们就是我们自己的主服务器和通讯服务主体。图 1-13 编译后得到的 EXE 文件(5)双击打开这两个可执行文件,如图 1-14 所示。可知默认情况下,MasterServer 使用的端口是 23466,而 Facilitator 使用的端口是 50005。Unity 网络多玩家游戏开发教程(内部资料) 版权所有 12 图 1-14 主服务器和通讯服务主体 1.3.2 连接到自定义的主服务器 本节将会编写脚本,使得游戏程序顺利连接到上一节下载到的自定义的主服务器,而非Unity 默认指定的主服务器上。(1)在当前的电脑上运行上一节编译得到的两个可执行文件 MasterServer.exe 和Facilitator.exe。因为是在当前的电脑上运行的,所以它们的 IP 就是 127.0.0.1。提示:如果 MasterServer.exe 和 Facilitator.exe 是运行在其它的电脑上的,就需要知道那台电脑的 IP 地址。(2)在Project视图里,新建C#脚本,命名为ExampleUnityNetworkingConnectToMasterServer,并添加下面的代码:01 using UnityEngine;02 using System.Collections;03 04 public class ExampleUnityNetworkingConnectToMasterServer:MonoBehaviour 05 06 /假定主服务器和通讯服务主体都运行在本机上 07 public string MasterServerIP=127.0.0.1;08 void Awake()09 10 /指定主服务器的 IP 地址和端口号 11 MasterServer.ipAddress=MasterServerIP;12 MasterServer.port=23466;13 /指定通讯服务主体的 IP 地址和端口号 14 Network.natFacilitatorIP=MasterServerIP;15 Network.natFacilitatorPort=50005;16 17 脚本 1015 行,明确的指定了自定义主服务的 IP 地址和端口号。如此一来,再连接服务器的时候,就不会在使用 Unity 默认指定的服务器了。(3)在 本 章“初 始 化 服 务 器”一 节,曾 编 写 过 一 个 脚 本Unity 网络多玩家游戏开发教程(内部资料) 版权所有 13 ExampleUnityNetworkInitializeServer,现将其与脚本ExampleUnityNetworkingConnectToMasterServer,一同赋予游戏场景中的 Main Camera 对象,然后运行游戏,效果如图 1-15 所示。说明新的连接已经建立,来自于当前主机的 25005 端口。图 1-15 连接到自定义的主服务器 1.4 注册“服务”联网玩同一游戏的玩家不只一位,所以在网络上也不会只存在一个服务。作为一个想要加入游戏的玩家而言,他需要从众多的服务中选择一个,然后再加入其中。不同的服务在网络上是通过“服务名”来标识的,而服务名是需要注册的。本节就来说明在网络上注册“服务名”,然后让其它玩家通过这个名称加入游戏的方法,如图 1-16 所示。Unity 网络多玩家游戏开发教程(内部资料) 版权所有 14 玩家1玩家2MasterServer注册连接特定服务服务名1服务名2.一同游戏的两位玩家玩家2注册 图 1-16 注册“服务”1.4.1 在主服务器上注册一个服务 MasterServer 上会显示所有的服务列表,但前提是游戏本身需要去主动注册。例如,上一节只是连接到了自定义的服务器,而没有注册,因此 MasterServer 上不会有任何输出。本节将会说明在主服务器上注册一个服务的方法。提示:只有一个玩家在 MasterServer 上注册了一个具体的服务以后,其它玩家才能加入这个服务,并一起游戏!(1)打开本章“初始化服务器”一节所创建的脚本 ExampleUnityNetworkInitializeServer,然后添加用于注册的代码:01 using UnityEngine;02 using System.Collections;03 04 public class ExampleUnityNetworkInitializeServer:MonoBehaviour 05 06 void OnGUI()07 08 if(GUILayout.Button(Launch Server)09 10 LaunchServer();11 12 13 /启动服务器 14 void LaunchServer()15 16 /接受来自 8 个主机的连接,监听的端口号是 25005,支持 NAT 穿透 17 Network.InitializeServer(8,25005,true);18 MasterServer.RegisterHost(GameTypeName1,gameName2,comment2);19 20 /Network.InitializeServer()调用完毕后,主动调用此方法 21 void OnServerInitialized()Unity 网络多玩家游戏开发教程(内部资料) 版权所有 15 22 23 Debug.Log(Server initialized);24 25 脚本 18 行的代码,就实现了“注册”的功能。调用的方法是 MasterServer.RegisterHost(),需要 3 各参数:第一个参数用于定义“服务类型名”;第二个参数用于定义“游戏名”;第三个参数用于定义“附加显示的信息”;(2)将脚本ExampleUnityNetworkInitializeServer与ExampleUnityNetworkingConnectToMasterServer,一同赋予游戏场景中的 Main Camera 对象,然后运行游戏,效果如图 1-17 所示。图 1-17 在 MasterServer 上注册一个服务器的效果 Unity 网络多玩家游戏开发教程(内部资料) 版权所有 16 1.4.2 在游戏视图上浏览特定服务 游戏可以在游戏视图上浏览 MasterServer 上的特定服务,然后选择一个服务加入其中。这就是本节要实现的效果。(1)在 Project 视图里,新建 C#脚本,命名为 ExampleUnityNetworkingBrowseServers,并添加下面的代码:01 using UnityEngine;02 using System.Collections;03 04 public class ExampleUnityNetworkingBrowseServers:MonoBehaviour 05 06 /表示当前是否正在加载 MasterServer 上的特定服务 07 private bool loading=false;08 /滚动条的初始位置 09 private Vector2 scrollPos=Vector2.zero;10 void Start()11 12 /自定义的用于请求 MasterServer 上特定服务的方法 13 refreshHostList();14 15 void OnGUI()16 17 if(GUILayout.Button(Refresh)18 19 refreshHostList();20 21 if(loading)22 23 GUILayout.Label(Loading.);24 25 else 26 27 scrollPos=GUILayout.BeginScrollView(scrollPos,28 GUILayout.Width(200f),GUILayout.Height(200f);29 /存储所有服务名的数组 30 HostData hosts=MasterServer.PollHostList();31 for(int i=0;i=ScoreLimit|p2score=ScoreLimit)27 28 /player 1 分数大于 player 2 29 if(p1score p2score)30 Debug.Log(Player 1 wins);31 /player 2 分数大于 player 1 32 if(p2score p1score)33 Debug.Log(Player 2 wins);34 /分数相同 35 else 36 Debug.Log(Players are tied);37 /开始新一轮的比赛 38 p1score=0;39 p2score=0;40 41 42 需要说明的是:一共可以有两位玩家同时游戏;分数达到胜利标准的玩家获胜;起始的分数是 0,赢一局加 1 分;Unity 网络多玩家游戏开发教程(内部资料) 版权所有 27 将此脚本赋予游戏场景中的 scorekeeper 对象。如图 1-26 所示,在 Inspector 视图上,可以设置玩家胜利的分数限制。图 1-26 Scorekeeper(Script)组件属性设置(2)乒乓球与球拍后的界限碰撞以后,是触发玩家分数改变(加 1 分)的契机。在 Project视图里新建一个 C#脚本,命名为 Goal,用于指定该给哪个玩家加分,代码如下:01 using UnityEngine;02 using System.Collections;03 04 public class Goal:MonoBehaviour 05 06 /在 Inspector 视图上,指定为哪位玩家加分,即 1 还是 2 07 public int Player;08 /表示 scorekeeper 对象上的 Scorekeeper(Script)组件 09 public Scorekeeper scorekeeper;10 public void GetPoint()11 12 /当乒乓球与球拍后的界限碰撞以后,触发分数的增加操作 13 scorekeeper.AddScore(Player);14 15 将此脚本赋予游戏场景中的 Goal_P1 和 Goal_P2 对象,然后在 Inpector 视图里分别设置各自的 Goal(Script)组件的属性,如图 1-27 所示。即碰到了 Player1 后的界限,就为 Player2加分,反之,为 Player1 加分。图 1-27 Goal(Script)组件属性设置(3)分数应该实时的显示在游戏视图上,玩家才能时刻知道此时自己的得分。下面就实现让分数信息显示于游戏视图上的功能。为游戏场景添加 3D Text 对象,命名为 p1Score,用于显示 Player1 的分数,设置其下列属性,如图 1-28 所示。Position:(-16,0,9);Rotation:(90,0,0);Scale:(1,1,1);Text:0;Unity 网络多玩家游戏开发教程(内部资料) 版权所有 28 Character Size:2;图 1-28 Text Mesh 组件属性设置(4)拷贝 p1Score,命名为 p2Score,用于显示 Player2 的分数,设置其下列属性:Position:(14,0,9);完成以上设置以后,游戏视图的效果如图 1-29 所示。可知显示玩家分数信息的对象,分别位于游戏视图的左上角和右上角。图 1-29 游戏视图中分数的显示位置(5)打开脚本 Scorekeeper,添加用于修改显示的分数的代码,添加代码如下:01 using UnityEngine;02 using System.Collections;03 04 public class Scorekeeper:MonoBehaviour 05 06 /表示获胜的分数 07 public int ScoreLimit=10;08 /Player1 的分数 09 private int p1score=0;10 /Player2 的分数 11 private int p2score=0;12 /表示表示 p1Score 的的 Text Mesh 组件组件 13 public TextMesh Player1ScoreDisplay;14 /表示表示 p2Score 的的 Text Mesh 组件组件 15 public TextMesh Player2ScoreDisplay;16 /加分操作 Unity 网络多玩家游戏开发教程(内部资料) 版权所有 29 17 public void AddScore(int player)18 19 /为 Player 1 加 1 分 20 if(player=1)21 22 p1score+;23 24 /为 Player 2 加 1 分 25 else if(player=2)26 27 p2score+;28 29 /检查是否有玩家达到了胜利的分数 30 if(p1score=ScoreLimit|p2score=ScoreLimit)31 32 /player 1 分数大于 player 2 33 if(p1score p2score)34 Debug.Log(Player 1 wins);35 /player 2 分数大于 player 1 36 if(p2score p1score)37 Debug.Log(Player 2 wins);38 /分数相同 39 else 40 Debug.Log(Players are tied);41 /开始新一轮的比赛 42 p1score=0;43 p2score=0;44 45 /修改修改 p1Score 显示的文本内容显示的文本内容 46 Player1ScoreDisplay.text=p1score.ToString();47 /修改修改 p2Score 显示的文本内容显示的文本内容 48 Player2ScoreDisplay.text=p2score.ToString();49