unity3d技术之多人游戏基础_第1页
unity3d技术之多人游戏基础_第2页
unity3d技术之多人游戏基础_第3页
unity3d技术之多人游戏基础_第4页
unity3d技术之多人游戏基础_第5页
已阅读5页,还剩3页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1.总览。 多人游戏基本结构:Clent/Server,分为 Authoritative Server 和 Non-Authoritative Server 两种,前者客户端发送消 息,服务器端反馈结果,好处是有效防止客户端作弊,并统一不同客户端之间的物理表现和互动状况,缺陷是存在网 络延时,很有可能每发出一个命令要过一段时间才能接收到反馈。解决方法是 client-side prediction 客户端预测,客 户端预测服务器的反馈,但不能做出关键性事件的预测,比如某个怪物的死亡。关于 client-side prediction 技术可以 到网上查阅相关资料,这里不赘述。 Non-Authoritative Sever 有客户端自己处理用户输入和对象逻辑,不需要要 client-side prediction 技术。这种情况服 务器端要处理的数据量相对比较小。 网络通信的方法:Remote Procedure Calls(RPC,远程进程调用)和 State Synchronization(状态同步)。 NAT punchthrough:网络连接可能是复杂的,比如中间要通过一个带公共 IP 的 NAT 路由器,怎样把 NAT 的内部私 有 IP 和外部计算机连接?可以利用一个叫做 Facilitator 的服务器和 private IP 接触并获知其所用的 IP 地址和端口号 。另外,内部防火墙玩家可以更改设置,外部防火墙也可以使用这种 NAT punchthrough 技术穿透。 Minimizing Network Bandwidth:最小化网络开支,只传输绝对重要的数据,比如客户端完全可以独立处理角色模型 而不需要服务器发送数据来同步。另外记住,你可以使用一个自带关卡标示的 RPC 调用来让所有客户端同时装载这个 关卡。 2.基础函数。 建立服务器:Network.InitializeServer(). 函数原型:static function InitializeServer (connections : int, listenPort : int, useNat : boolean) : NetworkConn ectionError 其中 connections 是允许连接数,useNat 是否允许 NAT punchthrough 连接。 一个初始化例子: ? 1 2 3 4 5 6 7 public class example : MonoBehaviour void LaunchServer() Network.incomingPassword = “HolyMoly“; bool useNat = !Network.HavePublicAddress(); Network.InitializeServer(32, 25000, useNat); 其中 Network.HavePublicAddress()查看是否拥有 IPV4 公共 IP.这是简单那的测试方法,另外一个更值得研究的方法 是 Network.TestConnction(). 建立连接到服务器:Network.Connect(). 熟悉一下 Network 类总是有好处。 使用 Network View 组件进行通信,这一点很重要,它让你可以使用 RPC 调用和 State Synchronization.每个组件有 一个唯一的 NetworkViewID,每个数据包都对应发送到一个由 NetworkViewID 指定的 Network View 所链接的对象 上。当使用 Network.Instantiate()创建 Network 对象时,会自动分配 Network View,不用开发者操心。当然你也通 过 RPG 调用在每个客户机上实例化一个 Network View 对象,然后使用 Network.AllocateViewID()函数手动分配 Net workViewID。 当你向一个对象添加 NetworkView 组件,并指定状态同步,需要选择 NetworkView 所监视的组件,这可以是该对象 的 transform,animation,script,或是 rigidbody.如果不使用状态同步而只是用 PRC 调用,则 state Synchronization 设 为 off 即可,只要有一个 Network View(不论是否开启 state Synchronization)你都可以使用 RPC. 设置 state Synchronization 为 Reliable Delta Compression,为可靠传输,数据按序发送接收。 同步监视对象是 script 时,需要使用 OnSerializeNetworkView 显式化序列数据: ? 1 2 3 4 function OnSerializeNetworkView (stream : BitStream, info : NetworkMessageInfo) var horizontalInput : float = Input.GetAxis (“Horizontal“); stream.Serialize (horizontalInput); 此代码当你本地更新或收到 stream 的更改时总是写 horizontalInput 的值。有时候你在本地更新和收到更新时,需要 做不同的事情,此时敲入如下代码: ? 1 2 3 4 5 6 7 8 9 10 11 12 function OnSerializeNetworkView (stream : BitStream, info : NetworkMessageInfo) var horizontalInput : float = 0.0; if (stream.isWriting) / Sending horizontalInput = Input.GetAxis (“Horizontal“); stream.Serialize (horizontalInput); else / Receiving stream.Serialize (horizontalInput); / . do something meaningful with the received variable 在 C#Script 中 Serialize()的参数是 ref 类型,在参数 horizontalInput 的前面加上引用符号 ref 即可。 OnSerializeNetworkView 的调用频率在 Network Manager 的 SendRate 里设置,默认是 15/s. 3.RPC 和状态同步。 如果要调用 RPC,所调用函数必须带有RPC 属性,如下: ? 1 2 3 4 5 6 var playerBullet : GameObject; function Update () if (Input.GetButtonDown (“Fire1“) networkView.RPC (“PlayerFire“, RPCMode.All); 7 8 9 10 RPC function PlayerFire () Instantiate (playerBullet, playerBullet.transform.position, playerBullet.transform.rotation); RPC 调用是可靠的有序的通信。 以下是使用 Network.AllocateViewID()手动分配 ViewID 的实例,其中使用 RPC 调用实例化 cubePrefab 的远程调用, ViewID 作为该远程调用的参数传递: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class example : MonoBehaviour public Transform cubePrefab; void OnGUI() if (GUILayout.Button(“SpawnBox“) NetworkViewID viewID = Network.AllocateViewID(); networkView.RPC(“SpawnBox“, RPCMode.AllBuffered, viewID, transform.position); RPC void SpawnBox(NetworkViewID viewID, Vector3 location) Transform clone; clone = Instantiate(cubePrefab, location, Quaternion.identity) as Transform as Transform; NetworkView nView; nView = clone.GetComponent(); nView.viewID = viewID; 那么,RPC (Remote Procedure Call)的规则和定义到底是什么? RPC 是某对象的脚本组件中包含的声明为RPC的(JS 为RPC)函数,这个对象必须包含一个 Network View 组件 ,并且监视对象是该脚本组件。这样,其他脚本就可以从远程通过这个对象调用该 RPC. RPC 函数的参数个数任意,但是为了减少网络消耗提高网络性能,个数最好优化到最少。 RPC 调用( Network.RPC())的参数还应加上 RPC 函数名称(string)和 RPCMode(接收对象,包括 All,Allbuffered, Others,Server 等等),接下来才是 RPC 函数的参数。 RPC 调用可以用来在所有客户端上执行某个事件,或者在两个特定的部分之间传递事件信息,你也可以创造性的发挥 。比如,一个游戏服务器只有当 4 个客户端连接上才开始游戏,当第四个客户端连上以后,服务器可以向所有客户端 同时发送 RPC 从而开始游戏。一个客户端可以向所有客户端发送 RPC 告知他拿到了某个物品。服务器可以在客户端连 接时发送 RPC 让客户端执行初始化,比如给它一个 player number,出生地点,队伍颜色,等等。客户端可以发送 R PC 定制它的启动设置,比如颜色偏好,已购物品等等。 NetworkMessageInfo 结构体中包含 timestamp 时间戳和 sender 发送者两个数据成员。在 RPC 函数的参数列表中加入 一项 NetworkMessageInfo,可自动获取该信息,而在 RPC 调用中不用显示列出该参数。 ? 1 2 3 4 5 RPC function PrintText (text : String, info : NetworkMessageInfo) Debug.Log(text + “ from “ + info.sender); RPC Buffer:使用 buffer 模式可以让你之前发送的 RPC 被新连接的客户端接受。比如向当前玩家发送装载某个关卡的 RPC,过段时间新玩家连接到游戏,需要装载当前其他玩家正在进行的关卡。这时新连接的玩家不会错过装载该关卡 的 RPC,因为它被缓存了起来。另外还可以刷新 buffer,比如开始新的关卡后新连接的玩家不如从之前的关卡开始一 个一个装载。 State Synchronization 的一些细节: 如前所述,状态同步的对象只能是以下四种类型之一:transform,animation,rigidbody 和 monobehaviour(也就是 scr ipt),其中 script 的需要用 onSerializeNetworkView()函数显示指定监视的变量数据。BitStream.Serialize()可接受的 参数可以是 bool,char,short,int,float,Quaternion,Vector3 和 NetworkPlayer.详情参考官方 script 手册中的 BitStream.S erialize(). 关于状态同步两种方式的选择: Reliable Delta Compressed:在属性级别自动对比当前状态(比如 position 和 rotation 是 transform 的两个不同属性 ,如果其中之一发生变动,只发送该变动数据),如果无变动则不发送。Unity 会利用 ACK 和 NACK 来保证 UDP 包 的发送可靠性,丢失的包会等待重传(是的,Unity 传输层使用的是 UDP 协议)。缺陷是网络不好会导致明显延时。 Unreliable:不保证可靠性,因此它不是仅仅发送更改的部分数据保留未更改的部分,而是每次更新都发送所有的数据 ,不管某部分改动还是未改动。这种模式用于游戏每帧都在变动的情况,比如赛车游戏。 综上,游戏变化频繁且迅速,而丢一两个包无关紧要,这时候选择 Unreliable,如果不是频繁变化,为了节省带宽,建 议选择 Reliable Delta Compressed. 4.Network.Instantiate. 此方法在每个客户机上实例化一个 prefab,并且是 buffered 型 RPC,这样当一个新的客户机连接到服务器后,会自动 实例化一个 prefab. 函数原型:static function Instantiate (prefab : Object, position : Vector3, rotation : Quaternion, group : int) : Object 其中 group(组)可以用来设置消息的过滤,如果不需要这个功能则设置为 0. 调用此 RPC 的例子: ? 1 2 3 4 5 6 public class example : MonoBehaviour public Transform playerPrefab; void OnConnectedToServer() Network.Instantiate(playerPrefab, transform.position, transform.rotation, 0); 可以用 Network.RemoveRPCs()函数来去掉 buffer 区的 Network.Instantiate()函数。你可以去掉特定组的 RPC(如果 Instantiate 指定了组的话),也可以去掉第一个 NetworkView ID 的 RPC,因为当实例化发生的时候 RPC 消息是与第 一个 Network View 连接的。 函数原型:static function RemoveRPCs (playerID : NetworkPlayer, group : int) : void 从 RPC buffer 里去掉 Instantiation 的例子: ? 1 2 3 4 5 6 7 8 9 public class example : MonoBehaviour void OnNetworkInstantiate(NetworkMessageInfo info) Debug.Log(networkView.viewID + “ spawned“); if (Network.isServer) Network.RemoveRPCs(networkView.viewID); Network.Destroy(gameObject); 组的作用:让特定(组)的客户端只能收到特定的消息。比如,如果两个玩家分隔在物理上互不影响的两个区域,但 是可以进行聊天。这时候他们之间游戏状态数据的交换就很有限,但是要保留聊天功能。物理上的游戏对象的实例化 就应该和提供聊天功能的对象的实例化分开,设定为不同的组。 5.Master Server: 在 Master Server 中可以显示所有的服务器,这样客户端可以在这里选择适合的服务器,另外 Master Server 隐藏端口 和 IP,解决连接问题,比如防火墙和 NAT 的 punchthrough. 每个游戏需要向 Master Server 提交一个 Game Type(注意避免和别的游戏重复),当客户端选择好 Game Type,M aster Server 会提供一个包含游戏人数、可能设置密码的运行中游戏列表。 这两个方法分别是:MasterServer.RegisterHost()(Host 端)和 MasterServer.RequestHostList()(客户端). 函数原型:static function RegisterHost (gameTypeName : String, gameName : String, comment : String = “) : void RegisterHost 的例子: ? 1 2 3 4 5 6 7 8 9 public class exam

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论