当前课程知识点:游戏程序设计 > 第十章 《网络同步技术》 > 10.4 常用同步方案 1 > 10.4 常用同步方案 1
接下来呢
我们来介绍一下
业界最常用的两种同步方案
一个是帧同步
一个是状态同步
好现在我们来分别
针对于一致性这个问题来看看
帧同步怎么样去处理的
我们来看看这两个Craft游戏
这两个游戏其实在当年
什么叫做网吧的黄金年代
可能大家没有经历过我经历过的
就那个时候可能个人电脑普及的比较慢
大家都没有电脑买不起
然后去网吧上网
那么在网吧里面大家玩什么的
都是玩这两个游戏
然后就他们采用的方案就是典型的帧同步
他们当时叫做锁步同步
然后呢
它们有个特点
就是如果玩过的同学就会知道
当有一个人掉线了
卡住了其他所有人都会等它
等它恢复之后游戏继续进行下去
这是当时我们的一个痛点大家都很痛恨
所以卡住了
然后大家都玩不了的
现在我们去玩王者
大家发现如果一个人网络不好对吧
他不好
并不影响我们自己的游戏对不对
于是
我们其实对帧同步进行一个改进
这就是所谓的现代帧同步和古典帧同步
后面我们有一个讨论
来讨论现代帧同步和古典帧同步
它们之间的一些区别
那么我们接下来看什么是帧同步
我借鉴一个游戏就龟兔赛跑
这是个寓言故事
我把游戏规则稍微改了一下
它的规则是什么样的
就是
这龟和兔呢
它不能随便动
它只有当裁判
我们现在有裁判吹着口哨
哎
这个龟兔才能够进行一次操作
它这次操作
可以是根据它的本身的特性
移动多少步比如龟可能慢点
兔快点对吧
但是它必须要在裁判吹口哨的时候
才做一次操作
因为我吹不出口哨
我就用响指表示吧
我们现在看看线下版本
那它线下版本
有一个规划
一个龟一个兔它们在赛跑
那我先打个响指
它们就移动了一步对吧
根据各自的速度往前移动一步
这个时候可能龟移的快点
兔子觉得这乌龟比较弱鸡
所以就先慢慢的走
然后又打个响指
它们又各自移动一步
这个时候兔子赶上乌龟了对不对
然后最后再打个响指
它们又移动的一步
它们差不多
这是一个线下版本
我们要将这样一个简单的游戏
把它做成一个线上版本
就是做成网游版本
那么做一个网游版本
必然就会有乌龟和兔子有各自的客户端嘛
对不对
上面是乌龟的客户端
下面是兔子的客户端
我们为了使两个客户端看起来画面是一样
于是呢
我们需要在乌龟的客户端里面
有个兔子的镜像
然后在兔子客户端里面
有个乌龟的镜像对吧
那么我们怎样让它们同步下去呢
我们继续遵循上面的规则
我们其实只需要
再下一次打响指之前
我们将龟和兔
它们各自即将要走的操作
同步给对方就可以了
比如说
我这个乌龟即将要移动
距离三
兔子即将要移动距离二
同步给对方同步给各自的镜像了
打个响指
它们就按照预定的这个操作进行移动
这个时候我们发现
两个客户端看起来一致
对不对
如法炮制
我们就会发现下面每一次
打响指之后
两个客户端看起来都是一致的
然后如法炮制
来看
一样一致那么
于是我们通过这种方式
让两个客户端保持了同步了
我刚刚打响指
可能打的速度不均匀
随便打的
那如果我们假设这个打的速度要均匀
而且频率非常快
固定是30Hz或者60Hz
会怎么样呢
于是我们就会得出
帧同步是什么意思呢
其实就是以固定的帧率同步玩家
下一帧的操作的一种同步方式很简单吧
这就是帧同步的一个本质
一个核心的一个思想
那么它的基本原理我也给大家介绍一下
那我就拿这个正弦函数举例
因为这个函数非常熟悉
那对于这个函数来讲
X轴和Y轴
假设这个函数X输入
fx是输出
如果我们给它一个输入一个输入1
那么它一定是有确定输出1
比如说这个是大概是一点几几对不对
它不可能两个输出
但是有一个输出吧
对不对
于是我们只要给它一个确定的输入
那么它必然会有个确认的输出
这是一个数学原理
那么我们来看
如果我们有两个函数
一样的函数两个函数一模一样
它们的参数也是一样的
函数逻辑也是一样的
都是sin函数
那么我们给它一个相同的输入
比如输入是相同的它们输出怎么样
显而易见
它们是有相同的输出的
这就是一个很简单的一个数学的一个原理
我们来回顾一下
我们前面刚刚说过的游戏程序
分层结构
我们可以将这个游戏的核心逻辑模块
看成一个函数
然后呢
将这个游戏的输入模块
看作这个函数的输入
那么输出控制模块
很显然就是这个函数输出了对吧
那么输出模块是什么呢画面
那么我们来看一下它这样一个结构图
这个结构图里面有三个关键点
其一就是这个等于号
它们的核心逻辑是相同的
然后呢
第二个关键点是它们具有当前状态
就是它们的一些参数相同的
然后第三个就它们输入是相同的
那么这样我们就可以得到它们的输出
也是可以同步的
那么
我们在前面那个图里面
这个书里面说时间之外
当然还包括我们好多其他的输入法
比如说各种操作
点击移动等等这些东西
那么所有这些东西我们已经知道了
那么我们来拿讨论怎样让这些东西
在两个客户端之间保持一致
这个时候我们就得要去介绍
有东西叫帧同步服务器
那么
帧同步服务器是什么样的一个原理呢
它其实是将时间在服务器上面
被拆分成相等的
一段一段的它其实就像一辆列车
像一列时间很长的列车一样
那么每一时间段就是这个列车
上面一个车厢
这个车厢呢
只有最近这个车厢的门是开的
其他车厢的门是不能开的
比如这个车厢的门是开的
最近一个时间段的车厢
而客户端的他们的各自的输入
它并不会直接
传递给它们的逻辑模块
而是透过客户端发送给服务器
然后就被服务器
当前开着门的这一节车厢给装进去了
那装上去之后
那么随着时间的流逝
下个时间段即将到来
再下个时间段到之前
就会将当前时间段的车厢里面的
所有的这些玩家的操作
把它同时发送给两客户端
我们可以通过一个动图来看一下
这是一个我们精心制作一个动图
你看
在动图里面
服务器将时间拆分成一段一段的
每段都有编号
然后客户端的逻辑
它是由服务器的帧驱动的
客户端平时不动的
那服务器的帧到了后才动一下
并且这个帧里面有些帧里面是
没有包含任何操作的
有些帧里面是包含操作的
客户端把操作发给了这个帧
装起来是15号都装下了
装起来之后
这个操作同时发出了两个客户端
常用这个动图
大家比较好
直观的去理解
刚才那个原理
我们可以做个实验
大家可以算一下这个函数
sin15
就算这样一个函数
如果大家有安卓手机
有ios可以算一下
你会发现
它们结果是不一样的
它们不仅精度不一样
你看他们在还没有到达精度的终点
它们在之前这里已经不一样了
这是一个在Windows平台
和IOS平台上面算的结果
假如我同样一个程序
比如说拿了个计算器
你用同样语言写就比如说
我就用C++和java写
在Windows跑和在ios跑
它们结果
其实也是不一样的
为什么不一样呢
是因为浮点数的计算
其实在CPU里面是有一个专门的单元
来处理的就是FPU
那么
每个设备FPU是不一样的
它们的内部精度是不一样的
所以它们算出来结果
其实就是不一样的
那么我们在游戏中
又不得不使用过的小数吗
对吧
那我们怎么办呢
其实大家不用担心
因为在FPU
FPU被发明之前得很早的时候
我们科学家其实也有需要去进行
各种小数的计算对不对
它们怎么做呢
它们是用定点数做的
什么是定点数
它其实就是用一个整数的运算
来模拟小数的运算
它其实就是将一个整数把它分了几部分
它分了一部分
比如说把最高的一位作为符号位
我们都知道是吧
零是正一是负数
然后的三十到十这一部分的位
给它表示一个小数的整数部分
那么后面应该表示这个小数的小数部分对吧
那通过这种方式
我们就能够再基于这样一种数字
数字的表达
我们来实现基于它的四则运算加减乘除
然后把加减乘除实现完之后呢
我们还是要实现开方运算以及超越函数
最后
我们需要实现基于定点数的随机函数
那么
除此之外
我们还有什么其他的方式
来得到一致的逻辑以及一致的状态的
那么
其实经过我们的工作经验的积累
我们经过了艰辛
数不清的bug各种经验
最后
我们得出这么几点
第一
第一部分我们必须要保证版本一致对吧
如果两个版本不一样
那必然是不可能得到一致性的逻辑对不对
然后我们需要不能依赖外部的
不确定的外部逻辑
哪怕你内部逻辑再怎么确定性
结果你不小心掉到一个外部的逻辑
结果你也不确定呢
对吧
还有一个限制外部逻辑
对我这个核心逻辑的调用
因为你也不知道
两个客户端的外部逻辑不一样了
那对核心我就要调用时机可能不一样
对不对
对不对
还有谨慎使用多线程
因为多线程的调度是由操作系统来决定的
而你的操心的不仅运行你
还会运行别的程序
两个手机的操作系统
运行别的程序是不一样的
于是就不能写多线程
或说你可以用一些其他的方式来实现
需要谨慎使用多线程
那么接下来
我们来讨论一个问题
就是如果你和别人去玩一个游戏
当你的网络卡了
你掉线了
你希望别人等你吗
那你和别人玩游戏
玩王者吧
然后你掉线你卡了
你说别人不动
等你等你恢复了再玩吧
大家都可能如果都会想是吧
让他等一下给我回复了
再玩
那么如果换了别人
如果别的网络卡了
那你希望别人等你吗
你需要你等别人吗
那肯定是不希望自己等别人对不对
对不对
那么就牵扯到一个问题
就当一个人网络卡住了
我们应该怎么办
这些就是一个古典帧同步
和现代帧同步的一个区别
对于古典帧同步来讲
比如说这客户端太卡是不是
他卡了
我不让它卡
必须让大家都在同一起跑线上
于是我们就会等他给他加几个凳子
让大家保持一致
你卡我们必须让你和我们有一样的体验
大家体验一样的看球一样的对吧
那么现在就不一样了
因为现在我们大家发现
大家都很关注个人体验
觉得个人体验爽就好了
不管别人怎么样对不对
那别人如果网络卡了
是他自己网络不好
于是现在帧同步让你卡了
你就看不到它了
大家体验是不一样的
只有现在帧同步
那我目前来讲
我们根据游戏的类型不一样
可能选择不同的方法去进行帧同步
那么接下来我们要给大家介绍一下
帧同步的优点和缺点
我们来看一下这个图中有两个大星号
为什么要用星号标起来
这其实想让大家注意一下
你看这个核心逻辑
有一半是黑
一半是灰的
就是说明它逻辑其实是不完整的
我们前面在介绍帧同步原理的时候
我们为了让帧同步
这个原理达成
所有客户端必须要运行完整的逻辑
我不能只运行我自己的逻辑
我必须运行所有人逻辑
那既然如此
每个客户端都运行着自己的完整逻辑
那么服务器
它就不需要核心逻辑对不对
于是服务器干嘛呢
它只需要进行收包或转发就可以了
它不需要运行逻辑
它只需要收包转发就可以了
于是我们就可以得到这样一个结果
就是无论这个逻辑再怎么复杂
无论从逻辑复杂的逆天了
客户端复杂服务器很简单
就收包转发收包转发是不是
那么由此我们可以得到它一个优点是什么
就是服务器逻辑很简单
对不对
因为服务器逻辑很简单
负载就很低
那服务器
研发周期整个研发周期会缩短
因为我开发的时候
我只需要关心客户端逻辑
那么大家缺点什么缺点呢
就是前面也说过了
反外挂问题很严峻
因为客户端它具有所有逻辑
包括那些
比如说我玩王者时候
那么有些人在视野范围之外的
一些逻辑其实还跑对吧
那我通过外挂让它显示出来
那没办法就出现反而挂的问题
而且这种外卦你还反不了
非常严峻
我们再来看一下这个动图
在这个动图里面
客户端逻辑是完全由服务器驱动
如果这个服务器没帧
下发客户端来驱动客户端的
时间往后面流动
如果由于网络的原因
网络断了
造成客户端收不到服务器的帧
那么这个时候其实客户端就不动了嘛
对不对就卡住对吧
那么
从另一个角度讲
由于客户端的唯一的输入
唯一的输入都来自于服务器
并且这个输入是一致的包括时间和和操作
使得客户端
它们之间具有很强很强的一致性
让它们一致性非常强
并且
我们的逻辑无论再怎么复杂
很复杂逻辑
但是你在玩的时候
你只有十个手指对不对
你只能操作你只有这么操作
你每一个
比如说我在一秒里面
我只能够点十次不能再多了
于是逻辑再怎么复杂
其实你的输入的量是非常少的
无论逻辑怎么复杂
那么基于这些
我们可以得到它的对比优缺点
但是还有一点
那么就是
帧同步我们前面看了龟兔赛跑时候
它其实它的每一步的正确同步与否
又取决于上一步对吧
上一步必须要同步
我这一步才能够这一步正常的同步
但是
如果我们不小心
在第二帧比如第二帧我发生了错误
那么这个错误可能发生了
但其实上
你通过观察后通过一些其它的检测方式
来检测到这个错误
我发现这个错误其实可能已经过了好久了
你可能在第九帧我们才发现这个错误
那这个时候对于错误的定位
和解决也是非常困难的
因为时间是不能倒流的
你在这个在这一帧你发现的错误
那你几个错误你得知道错了源头是不是
但时间也不能倒流
于是你想去定位这个源头其实是很难的
那它带着一对优缺点是什么
优点就是一致性很高
而且它的同步流量很小
那么同步流量小带宽成本就小
然后它缺的就是
它对网络延时等敏感度非常高
网络只要稍微有延时就卡
然后它的一些不同的问题
非常难以定位和解决
那么
除了前面的两对优缺点之外
那么后面还有一个优缺点
什么呢
它天然支持观战录像后回放
那么它有缺点
就是单局规模受限
为什么会有这一堆缺点的这个问题
可以留给大家在课后去思考
为什么会有还会有这一对优缺点
根据前面的优缺点
我们可以得知它应用场景
首先适合单据规模适中的
但又不能太大
然后不能中途加入角色
然后它的时间要求比较高
那我比如说像ACT类比较适合用帧同步
比如像格斗类纯格斗类
比较适合用这个帧同步
比如说像体育类
然后再就是像RTS这种
还有ARTS也就是moba
-1. 1什么是游戏(上)
--选择题
-1.2 什么是游戏(下)
--选择题
-1.3 游戏是如何开发出来的
-1.4 游戏引擎(上)
-1.5 游戏引擎(下)
--单选题
-1.6 如何成为一个游戏开发者
--多选题
-2.1 什么是游戏服务器
--单选题
-2.2 游戏服务器的和分类发展
--单选题
-2.3 核心技术和实现难点
--单选题
-2.4 设计原理与方法论
--单选题
-3.1 三维坐标系统
--多选题
-3.2 向量与运算
--单选题
-3.3 矩阵与线性变换
--双选题
-3.4 四元数
--3.4 四元数
--多选题
-4.1 游戏循环概述(上)
--多选题
-4.2 游戏循环概述(下)
--单选题
-4.3 《无尽之路》的实现
--单选题
-4.4 支撑游戏的功能
--选择题
-4.5 支撑游戏的机制与系统
--多选题
-5.1 基本介绍
--5.1 基本介绍
--单选题
-5.2 随机数生成器
--单选题
-5.3 随机数分布与应用
--单选题
-6.1 什么是游戏玩法开发
--单选题
-6.2 建立愿景 Vision
--单选题
-6.3 划定边界 Scope
-6.4 迭代 Iteration
--单选题
-6.5 迭代 Iteration+抛光Polish
--单选题
-7.1实时图形渲染管道 宏观渲染系统
--单选题
-7.2实时图形渲染管道 应用阶段
--单选题
-7.3实时图形渲染管道 几何阶段
--单选题
-7.4实时图形渲染管道 光栅化阶段
--单选题
-7.5实时图形渲染管道 总结 参考
-8.1 物理回顾1
--单选题
-8.2 物理回顾2
--单选题
-8.3 材质 1
--8.3 材质 1
-8.4 材质 2
--8.4 材质 2
-8.5 材质3
--8.5 材质3
-8.6局部光照
--8.6局部光照
--单选题
-8.7 全局光照
--8.7 全局光照
--单选题
-9.1 动画介绍
--9.1 动画介绍
--多选题
-9.2 游戏动画介绍
-9.3 动画技术类型
--多选题
-9.4 骨骼蒙皮动画
--多选题
-9.5 动画流水线
--多选题
-9.6 动画前沿趋势
--多选题
-10.1 .基本概念
--多选题
-10.2 设计目标
--多选题
-10.3 传输数据分析
--多选题
-10.4 常用同步方案 1
-10.4 常用同步方案 2
-10.4 常用同步方案 3
-10.4 常用同步方案 4
--多选题
-10.5 方案对比
--多选题
-11.1 基本图元
--单选题
-11.2 图元距离(上)
--单选题
-11.2 图元距离(下)
--单选题
-11.3 图元相交测试+ 其他几何方法
--单选题
-12.1 著名物理引擎介绍
--单选题
-12.2 物理引擎原理(上)
--单选题
-12.3 物理引擎原理(下)
--单选题
-12.4 游戏中的物理体
--单选题
-12.5 物理引擎使用入门
--单选题
-13.1开发语言
--13.1开发语言
--单选题
-13.2 开发环境
--单选题
-13.3 腾讯开发组件介绍
--单选题
-13.4 网络通信+业务框架介绍
--多选题
-14.1 进程间通信(上)
-14.2 进程间通信(下)
-14.3 通信格式
-14.4 并发模型
-14.5 超时处理
-14.6 大系统小做(上)
--多选题
-14.7 大系统小做(下)
-14.8 架构层面的技术支持(上)
--单选题
-14.9 架构层面的技术支持(下)
-14.10 分布系统的关键能力
--多选题
-15.1 游戏人工智能综述
-15.2 人工智能在游戏中主要方法 上
--多选题
-15.3人工智能在游戏中主要方法 (下)
-15.4 人工智能在游戏制作中的应用领域1
--多选题
-15.5 人工智能在游戏制作中的应用领域2
-15.6 人工智能在游戏制作中的应用领域3
--多选题
-15.7 人工智能在游戏运营中的应用实践(上)
-15.8 人工智能在游戏运营中的应用实践(下)
--多选题
-16.1 游戏支撑系统(1)
--单选题
-16.2 游戏支撑系统(2)
--单选题
-16.3 游戏支撑系统(3)
--单选题
-16.4 游戏支撑系统(4)
--单选题
-16.5 游戏支撑系统(5)
-17.1 游戏逻辑服务器(上)
--单选题
-17.1 游戏逻辑服务器(下)
-17.2 外挂与反外挂(上)
-17.2 外挂与反外挂(下)
--多选题
-18.1运行环境
--18.1运行环境
--多选题
-18.2物理部署
--18.2物理部署
--多选题
-18.3系统的可运维性
--多选题
-18.4运维案列分析
--多选题