Skip to main content

分布时间同步的技术细节

开始本部前,确保你已具备所需的前置知识,并且了解分布时间同步的基本概念

在VRChat 每隔 0.2秒会对 Avatar 的同步参数发起同步 (Sync Interval(同步间隔) = 0.2s),而同步的信息抵达远端玩家的时间大约在 0.1 - 1.0秒 (Latency = 0.1 ~ 1.0)


同步步骤,Bit 数与延迟 (续)


上一章节提到,同步步骤决定了可节省的 bit 数,以及带来的延迟。

同步步骤可节省的 bit 数可以由以下公式计算:

image.png

计算同步参数 bit 节省的公式

不同类型需(Bool, Int && Float) 需独立计算。 Int 及 Float 可以互相转换而不损失过多精度,固计算和同步时可以视作同一类型

同步步骤带来的延迟可以由以下公式计算:

image.png

计算同步步骤延迟的公式

在某个同步步骤数量下所需的同步容器的数量可以由以下公式计算:

image.png

计算所需同步容器数量的公式

举例,如果有10个integer,在4步同步的情况下:

  • 原本需要 7 * 10 = 70 bit
  • 使用4步时,需要 10/4 = 2.5 ^= 3 个整数
  • 使用4步时,7 * 3 = 21 bit
  • 节省 49 bit
  • 带来延迟 4*0.2 = 0.6s

分布时间同步架构的细节


一个分布时间同步系统的架构包含远端区分发送器接收器同步容器(Bool, Int, Float*),时序标记(Bool)

Int 及 Float 可以互相转换而不损失过多精度,固计算和同步时可以视作同一类型,同步时发射器将 Float 转换为 Int,接收器反之

分布时间同步架构的运行

具体来说,分布时间同步架构的运作逻辑是这样的:

  • 远端区分来判断当前 Avatar 应使用接收器发射器
  1. 发射器将要传递的参数数值输入到对应的同步容器内,同时设定好时序标记
  2. 同步容器并且在0.2秒的同步间隔结束后向远端的接收器发送。
  3. 接收器接收到时序标记的变化,将同步容器里的内容保存到它对应的参数中。

重复以上步骤,直到所有步骤完成,即完成一次完整同步,最后从步骤1开始循环。

实现分布时间同步的方法并不唯一,只要符合其原理即可

同步容器 && 时序标记

同步容器和时序标记分别用于承载要同步的参数数值以及指示接收器开始接收内容。同步容器视乎情况,可能需要使用多个以传递所有类型的参数和降低传输延迟。而时序标记则取决于你决定使用多少同步步骤。

将多个时序标记视为一组以二进制表示的数值,容纳步骤数量所需的二进制位数即为时序标记所需的数量:

  • 2步 = 1位 (0, 1)
  • 3步 = 2位 (00, 01, 10, 11)
  • 4步 = 2位 (00, 01, 10, 11)
  • 5步 = 3位 (000, 001, 010, 011, 100, 101, 110, 111)
  • ...

远端区分

远端区分是一个极为简单的模块,它的唯一作用是在 Avatar 初始化时区分其所属 Avatar 当前为由玩家正在穿着的本地 Avatar,或者是由远端玩家观察的 Avatar,并由此决定该 Avatar 是传输源头还是传输终点。

一般来说,使用 IsLocal做出区分即可。

image.png

远端区分模块的例子

发射器

分布时间同步系统中的发射器负责将本地 Avatar 中的值输入到同步容器中,并且也要负责设定同步时序,以免发送的信息被输入到错误的参数中。

同步参数以每0.2秒的间隔发送,故每个步骤间需间隔0.2秒

image.png

发射器通过 Parameter Driver 将参数储存到同步容器中,以及设定同步时序

接收器

分布时间同步系统中的接收器负责视乎时序,将同步容器中的值输入到对应的参数中。

Wait For Interval 是一个为了防止状态转变过快而使 Parameter Driver 被跳过的安全措施,离开该状态的 Transition 需要勾选 Exit Time,具体 Exit Time 不重要

image.png

接收器通过 Parameter Driver 将同步容器中的信息储存到参数中