分步同步的技术细节
开始本部前,确保你已具备所需的前置知识,并且了解分布时间同步的基本概念
在VRChat 每隔 0.2秒会对 Avatar 的同步参数发起同步 (Sync Interval (同步间隔) = 0.2s),而同步的信息抵达远端玩家的时间大约在 0.1 - 1.0秒 (Latency = 0.1 ~ 1.0)。
同步步骤,Bit 数与延迟 (续)
上一章节提到,同步步骤决定了可节省的 bit 数,以及带来的延迟。
同步步骤可节省的 bit 数可以由以下公式计算:
计算同步参数 bit 节省的公式
不同类型需(Bool, Int && Float) 需独立计算。 Int 及 Float 可以互相转换而不损失过多精度,固计算和同步时可以视作同一类型
同步步骤带来的延迟可以由以下公式计算:
计算同步步骤延迟的公式
在某个同步步骤数量下所需的同步容器的数量可以由以下公式计算:
计算所需同步容器数量的公式
举例,如果有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 远端传输时只有 1/127 的精度 (8 bit quantization), Int 则可以完全保有 1/256 的精度,故同步时可以在发射器将 Float 转换为 Int,接收器逆向转换,这样可保有最大精度。
分布时间同步架构的运行
具体来说,分布时间同步架构的运作逻辑是这样的:
- 远端区分来判断当前 Avatar 应使用接收器或发射器
- 发射器将要传递的参数数值输入到对应的同步容器内,同时在每一步都设定好时序标记。
- 同步容器的内容在0.2秒的同步间隔结束后向远端的接收器发送。
- 接收器接收到时序标记的变化,将同步容器里的内容保存到它对应的参数中。
重复以上步骤,直到所有步骤完成,即完成一次完整同步,最后从步骤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)
- ...
或者,你也可以单纯的使用 Int 来作为时序标记,在同步步骤多余7步的时候使用 Bool 作为时序标记的 Parameter 利用效率更高
远端区分
远端区分是一个极为简单的模块,它的唯一作用是在 Avatar 初始化时区分其所属 Avatar 当前为由玩家正在穿着的本地 Avatar,或者是由远端玩家观察的 Avatar,并由此决定该 Avatar 是传输源头还是传输终点。
一般来说,使用 IsLocal
做出区分即可。
远端区分模块的例子
发射器
分布时间同步系统中的发射器负责将本地 Avatar 中的值输入到同步容器中,并且也要负责设定同步时序,以免发送的信息被输入到错误的参数中。
同步参数以每0.2秒的间隔发送,故每个步骤间需间隔0.2秒
发射器通过 Parameter Driver 将参数储存到同步容器中,以及设定同步时序
接收器
分步同步系统中的接收器负责视乎时序,将同步容器中的值输入到对应的参数中,是发射器的逆向操作。接收器的时序可以使用任何形式(int, bool 或者其他你认为合适的方法),未必限定在样图中的形式。接收器也不需要关心 0.2s 的同步间隔,只需要不断尝试接收即可。
接收器通过 Parameter Driver 将同步容器中的信息储存到参数中
No Comments