译:unet网络概述(3)

状态同步

状态同步是从服务器到远程客户端完成的。本地客户端没有它的串行化数据,因为它与服务器共享场景。串行到本地客户端的任何数据都将是冗余的。然而,在本地客户端上调用数据与SyncVar挂钩。

数据未从远程客户端同步到服务器。这是指令的工作。

SyncVars

SyncVars是从服务器同步到客户端的NetworkBehaviour脚本的成员变量。当一个对象被产生或者一个新玩家加入正在进行的游戏时,它们将接收到视域中所有网络物体的SyncVars的最新状态。在调用OnStartClient()之前,SyncVars的状态应用于客户端上的对象,因此该对象的状态保证在OnStartClient()内是最新的。SyncVars可以是基本数据类型,如整数,字符串和浮点数。它们也可以是Unity类型,例如Vector3和用户定义的结构,但是对于SyncVars的更新作为单片更新发送,而不是在结构中的字段更改时的增量更改。在单个NetworkBehaviour脚本中最多可以有32个SyncVars,这包括SyncLists。

当SyncVar的值更改时,服务器会自动发送SycnVar更新。没有必要对SyncVars执行任何手动清理字段。

同步列表

SyncLists类似于SyncVars,但它们是值列表,而不是单个值。SyncList内容包括在具有SyncVar状态的初始状态更新中。SyncLists不需要SyncVar属性,它们是特定的类。对于基本类型,有内置的SyncList类型:

• SyncListString

• SyncListFloat

• SyncListInt

• SyncListUInt

• SyncListBool

还有SyncListStruct,可以用于用户定义的结构列表。使用的结构SyncListStruct派生类可以包含基本类型,数组和常见Unity类型的成员。它们不能包含复杂类或通用容器。

SyncLists具有名为Callback的SyncListChanged委托,允许在列表内容更改时通知客户端。将使用发生的操作类型和操作所针对的项目的索引来调用此代理。

自定义串行化函数

通常,使用SyncVars足以让脚本将其状态串行化到客户端,但在某些情况下需要更复杂的串行化代码。开发人员可以利用NetworkBehaviour上用于SyncVar串行化的虚拟函数来执行自己的自定义串行化。这些功能是:

public virtual bool OnSerialize(NetworkWriter writer, bool initialState);

public virtual void OnDeSerialize(NetworkReader reader, bool initialState);

initialState标志用于区分对象第一次串行化和可以发送增量更新时。第一次将对象发送到客户端时,它必须包括完整状态快照,但后续更新可以通过仅包括增量更改来节省带宽。请注意,当initialState为true时,不调用SyncVar钩子函数,仅用于增量更新。

如果一个类有SyncVars,那么这些函数的实现会自动添加到类中。因此,具有SyncVars的类也不能具有自定义串行化函数。

OnSerialize函数应返回true时指示发送更新。如果它返回true,那么该脚本的脏位被设置为零,如果它返回false,那么脏位不改变。这允许对脚本的多个更改随时间累积,并在系统就绪时发送,而不是每个帧。

串行化流

具有NetworkIdentity组件的游戏对象可以具有源自NetworkBehaviour的多个脚本。串行化这些对象的流程是:

在服务器上:

• 每个NetworkBehaviour有一个脏面具。此掩码在OnSerialize中作为syncVarDirtyBits可用

• NetworkBehaviour脚本中的每个SyncVar在脏掩码中分配一位。

• 更改SyncVars的值会使该SyncVar的位在脏掩码中设置

• 或者,调用SetDirtyBit()直接写入脏掩码

• NetworkIdentity对象在服务器上作为其更新循环的一部分被检查

• 如果NetworkIdentity上的任何NetworkBehavours是脏的,则为该对象创建一个UpdateVars包

• 通过在对象上的每个NetworkBehavail上调用OnSerialize来填充UpdateVars数据包

• 没有脏的NetworkBehavours向它们的脏位写入一个零

• 脏的NetworkBehavours写它们的脏掩码,然后更改SyncVars的值

• 如果OnSerialize对于NetworkBehaviour返回true,则脏掩码将针对该NetworkBehaviour重置,因此它将不再发送,直到它的值更改。

• UpdateVars数据包发送到正在观察对象的就绪客户端

在客户端:

• 接收对象的UpdateVars分组

• 对对象上的每个NetworkBehaviour脚本调用OnDeserialize函数

• 对象上的每个NetworkBehaviour脚本读取脏掩码。

• 如果NetworkBehaviour的脏掩码为零,OnDeserialize函数将不再读取返回

• 如果脏掩码为非零值,则OnDeserialize函数读取与所设置的脏位相对应的SyncVars的值

• 如果有SyncVar钩子函数,那些被从流读取的值调用。

如果NetworkBehaviour有一个基类也有串行化函数,基类函数也应该被调用。

注意,为对象状态更新创建的UpdateVar分组可以在被发送到客户端之前聚合在缓冲器中,因此单个传输层分组可以包含多个对象的更新。

远程操作

网络系统具有在网络上执行动作的方法。这些类型的操作有时称为远程过程调用。在网络系统中有两种类型的远程过程调用:Commands - 从客户端调用并在服务器上运行; 和ClientRpc调用 - 它们在服务器上调用并在客户端上运行。

下图显示了远程操作采取的方向:

示意图

Commands

命令从客户端上的Player对象发送到服务器上的Player对象。为了安全起见,命令只能从你的玩家对象发送,所以你不能控制其他玩家的对象。要将某个函数转换为命令,请向其中添加[Command]定制属性,并添加“Cmd”前缀。此函数现在将在服务器上在客户端上调用时运行。任何参数将自动使用命令传递到服务器。

命令函数必须具有前缀“Cmd”。当读取调用命令的代码时,这是一个提示 - 这个函数是特殊的,不象普通函数那样在本地调用。

小心从客户端每帧发送命令!这可能会导致大量的网络流量。

默认情况下,命令在通道0(默认可靠通道)上发送。因此,默认情况下所有命令都可靠地发送到服务器。这可以使用[Command]自定义属性的“Channel”参数进行自定义。此参数应为一个整数,表示通道号。

通道1也默认设置为不可靠通道,因此要使用此参数,请在Command属性中使用值1作为参数,如下所示:

         [Command(channel=1)]

从Unity 5.2版开始,可以从具有客户端权限的非玩家对象发送命令。这些对象必须已使用NetworkServer.SpawnWithClientAuthority衍生,或者使用NetworkIdentity.AssignClientAuthority设置权限。从这些对象发送的命令在对象的服务器实例上运行,而不是在客户端的关联Player对象上运行。

ClientRpc调用

ClientRpc调用从服务器上的对象发送到客户端上的对象。它们可以从具有已生成的NetworkIdentity的任何服务器对象发送。由于服务器具有权限,因此服务器对象在发送这些调用时不存在安全问题。要将函数变成ClientRpc调用,请向其中添加[ClientRpc]定制属性,并添加“Rpc”前缀。此函数现在将在客户端上在服务器上调用时运行。任何参数将自动传递给ClientRpc调用的客户端..

ClientRpc函数必须具有前缀“Rpc”。当读取调用方法的代码时,这是一个提示 - 这个函数是特殊的,不象普通函数那样在本地调用。

当使用LocalClient作为主机运行游戏时,ClientRpc调用将在LocalClient上调用 - 即使它与服务器处于相同的进程。因此,LocalClients和RemoteClients的行为对ClientRpc调用是相同的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,802评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,109评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,683评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,458评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,452评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,505评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,901评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,550评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,763评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,556评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,629评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,330评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,898评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,897评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,140评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,807评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,339评论 2 342

推荐阅读更多精彩内容