timewrap 算法
何为延迟补偿?如何进行坐标差值?B客户端屏幕上A已经跑到东边了,但是收到服务器说“A正在西边往北跑”,B到底该何去何从?我若干年前的一个实现版本,将简明扼要的解决这个问题:
影子跟随算法由普通DR(dead
reckoning)算法发展而来,我将其称为“影子跟随”意再表示算法同步策略的主要思想:
屏幕上现实的实体(entity)只是不停的追逐它的“影子”(shadow)。
服务器向各客户端发送各个影子的状态改变(坐标,方向,速度,时间)。
各个客户端收到以后按照当前重新插值修正影子状态。
影子状态是跳变的,但实体追赶影子是连续的,故整个过程是平滑的。
前面的1号终端控制红色飞船P1向左飞,并把自己的状态时时告诉服务器。
后面的2号终端上接收到飞船P1的影子S1的状态(向左移动),并让P1的实体追赶S1。
网络性能指标一:带宽,限制了实时游戏的人数容量。
网络性能指标二:延时,决定了实时游戏的最低反应时间。
使用该算法可以容易的开发出一款马里奥赛车,或者Counter Strike,详细说明见后:
算法比较:
帧间同步:不同客户端每帧显示相同的内容,键盘/时钟数据传到服务器,服务器确认后所有终端做出响应,多用于局域网游戏,比如红警(需要等待客户端),街霸II的网络版(360),可参考 LockStep,TimeWrap算法,网速要求高,复杂度低,见我的旧文帧锁定算法。
插值同步:不同客户端显示不同步,但是状态同步,常见的Dead Reckoning(或叫导航插值),效果好,但复杂度高。常见于竞速类游戏和 FPS游戏。
算法定义:
时间:单位为帧(FPS=10),开始由服务器告诉向所有客户端,每5分钟同步。
玩家:每个玩家控制自己的实体,并在每贞将状态改变告知服务器。
状态:状态数据 = 实体ID + 坐标 + 方向 + 速度 + 时间(贞)。
插值:收到新状态包后将根据其运动方向与时间,根据现有时间计算新状态。
跟随:实体不停的追踪自己的影子,追上后与影子保持状态同步。
相位滞后:可选参数,实体与影子保持一定距离同步,相当于保持一定车距,这样在控制者突然停止的时候,不容易因为网络延迟跑过了又被拉回来。
惯性移动:可选参数,开始移动或者停止或者改变方向都有加速度,这样就不需相位滞后了。
每次服务器向各个客户端同步时间的时候,由于延迟,所有客户端的时间都是慢于服务器的,这没有关系,只要大家在一定误差范围内以相同的速度增加,就完全没有问题。
图2 IDC网络响应
在公网平均130ms的Latency下,是不存在“完全的”的同步情况。如何通过消除/隐藏延时,将用户带入快速的交互式实时游戏中,体验完美的互动娱乐呢?
让所有的用户屏幕上面表现出完全不同的表象是完全没有问题的;
把这些完全不同表象完全柔和在一个统一的逻辑中也是完全没有问题的。
需要根据具体情况,分清楚哪些我们可以努力,哪些我们不值得努力,弄明白实时游戏中同步问题关键之所在,巧妙的化解与规避游戏,最终在适合普遍用户网络环境中(200ms),实现实时快速互动游戏。
案例解析:Counter Strike
实现CS的话,首先我们需要给人物移动加上惯性,比如静止状态突然开始移动,那么需要0.5-1秒的加速过程,而移动中突然停止也需要0.5-1秒的减速过程,这样就实现了无差别同步,不需要相位滞后来避免拉扯影响用户感。
同时开枪射击采用客户端判断,也就是说如果我看见你在墙前面,开枪射中,那么我向服务器发送“我击中你了”,这时有可能真实的你在墙后,那么表现出来的就是我看见我打中你了(减不减血由服务段判断),而你没有看见我,觉得我穿墙打中你了。
图3 CS的同步逻辑
关键状态进行缓存,不然如果别人向前连续跳五次,每次取得状态都取到最高点的话,别人客户端上的影子和跟随的实体会奇怪的持续的飞在天上,所以需要将起跳和落地这两个关键状态缓存,实体追赶时只有追上的第一个状态(一号影子)才能追逐第二个状态(二号影子)。
由此可以在完全时间同步的情况下平滑的跑动、跳跃,开枪射击采用客户端判断后手感得到提高,唯一需要担心的就是外挂,外挂多是实时游戏的代价,只能通过Cheating Death等工具防止了。
案例解析:马里奥赛车
用该算法实现马里奥赛车是很简单的,影子和实体都使用惯性,由于赛车惯性很大,不容易有突变的状态更新,所以效果会比FPS游戏更好。
玩家碰到道具后,马上在屏幕上隐藏该道具的显示并通知服务器,由服务器决断道具属谁,由于刚碰到道具就隐藏所以不会有碰到道具却在一段时间内无法取得延迟现象。
游戏道具系统实现也很容易,比如那个将当前第一名炸毁的道具,它的描述是:原角色+对象角色+约定发生时间。既然知道对象是谁,什么时间发生,那就更本不需要怎么同步了,所有客户端和服务器在该时间让炸弹爆炸就得了,这种手法类似即时战略游戏。
游戏还有一类道具是可以发射的乌龟壳,这个东西属于有弹道的发射物,类似Quake里面的某些武器,需要作一些同步处理,基本特性是服务器判断起决定作用,客户端同步判断,如果客户端与服务器都判断集中,那就集中;如果客户端判断集中而服务器判断没有集中,那会看到该角色似乎被打了一下,但很快又恢复了速度向前冲。
由于赛车本身就具备惯性比较大的特点,因此同步效果是比较好的,可以在更大的延迟情况下表现得和FPS差不多(比如300ms效果相当于FPS的200ms)。
非可靠包:
该“影子跟随算法”支持非可靠传输协议,如果使用非可靠传输,那么我们按照特定频率(如每秒10次)定时发送状态更新,因为协议中每个更新包出了位置外还有速度、方向和时间,甚至还能加速加速度,因此我们丢一个包没有关系,可以根据后来的包重新计算插值。只有关键状态更新时才需要可靠传输,这就避免了TCP中丢包时RTO指数增长造成的延迟了。
负面情况:
该算法缺点就是无法向“帧间同步”算法那样,每次发送按键给服务器,服务器处理后再反馈结果,在局域网中(平均延迟<5ms),这样的效果相当于单机游戏一样即时,游戏性也能很复杂。然而在Internet中(平均延迟130ms,设计基准200ms,每秒最多发送10个数据包)该算法却不能像单机游戏那样有复杂的场景互动,有类似格斗游戏的即时的动作判定。
许多策划在设计实时动作游戏时很多设计我们都难以实现,这样因为策划不容易明白哪些我们能做,哪些我们不能做。即便程序员精通同步理论,策划也经常碰壁。
当多数设计被程序员回复“无法实现”后,策划只有采取一种消极设计(砍掉很多有意思的互动元素),于是网络游戏的表现力到今天还是差单机游戏一大截。
这些问题也并不能因为“影子跟随算法”的提出而得到改进,大于100ms的判定时间,都很难做到即时。
最后,该算法编码复杂度比其他同步策略高,因为服务器需要计算一份影子数据,各个客户端需要计算一份影子数据,还需要计算实体追赶,而这三种计算都需要在同样的时钟下保持一致,这就增加了编码与调试的复杂度。
总结话题:
Internet特点是“高带宽,高延迟”,可以说从本质上Internet就不是为了游戏而设计的。故此Internet绝对意义的同步是不存在的。“影子跟随算法”的核心思想有几个:时钟同步,客户端先行,平滑追赶。通过这三个特性,我们能够在近似时间同步的情况下,模拟各种物体的移动过程,而使用该算法的前提是设计者需要根据各个游戏的特性研究不同的优化技巧,策略因游戏而变。
比如发送状态更新包时,不需要每次都发送,而可以只发送改变的状态。什么时候我们觉得改变了?就是当客户端实体与自己的影子之间的误差大于某特定数值时我们才发送更新包,这样虽然玩家在原地做左右摇摆的小幅度移动,只要没有超出范围,都不需要发送新的状态更新,其他玩家机器上看起来,它是站着不动的。
比如当发现某客户端5秒钟没有相应了,那么就将该人物的影子冻结住,永远不要为了等待某个数据而不让游戏进行下去。
本算法需要客户端与服务器维护相同的时钟,当每5分钟同步的时候,直接根据服务器的时钟替换当前时钟就行了,不需要重新计算所有影子的位置,因为后续的状态数据将会马上刷新这些状态。更不需要将测量到的PING值考虑进去,该算法与PING具体值无关。
当发现策划案子不可行时,寻找近似替代方案,比如减少“一次性的”“决定性的”事件发生,比如延长导弹在空中飞行的时间,比如将敌人加入HP分多次打死,而不是以及毙命,等等,都是大家可以发挥想象的地方。
timewrap 算法的更多相关文章
- Python之算法
一.什么算法 算法:一个计算过程,解决问题的方法 二.时间复杂度 看代码: ...
- 九大常用排序算法 python
1.冒泡排序 import random from timewrap import * @cal_time def bubble_sort(li): for i in range(len(li)-1) ...
- python之算法LOB三人组
一.冒泡排序 a.冒泡排序----优化 如果冒泡排序中执行一趟而没有交换,则列表已经是有序状态,可以直接结算法 import random from timewrap import * @cal_ti ...
- B树——算法导论(25)
B树 1. 简介 在之前我们学习了红黑树,今天再学习一种树--B树.它与红黑树有许多类似的地方,比如都是平衡搜索树,但它们在功能和结构上却有较大的差别. 从功能上看,B树是为磁盘或其他存储设备设计的, ...
- 分布式系列文章——Paxos算法原理与推导
Paxos算法在分布式领域具有非常重要的地位.但是Paxos算法有两个比较明显的缺点:1.难以理解 2.工程实现更难. 网上有很多讲解Paxos算法的文章,但是质量参差不齐.看了很多关于Paxos的资 ...
- 【Machine Learning】KNN算法虹膜图片识别
K-近邻算法虹膜图片识别实战 作者:白宁超 2017年1月3日18:26:33 摘要:随着机器学习和深度学习的热潮,各种图书层出不穷.然而多数是基础理论知识介绍,缺乏实现的深入理解.本系列文章是作者结 ...
- 红黑树——算法导论(15)
1. 什么是红黑树 (1) 简介 上一篇我们介绍了基本动态集合操作时间复杂度均为O(h)的二叉搜索树.但遗憾的是,只有当二叉搜索树高度较低时,这些集合操作才会较快:即当树的高度较高(甚至一种极 ...
- 散列表(hash table)——算法导论(13)
1. 引言 许多应用都需要动态集合结构,它至少需要支持Insert,search和delete字典操作.散列表(hash table)是实现字典操作的一种有效的数据结构. 2. 直接寻址表 在介绍散列 ...
- 虚拟dom与diff算法 分析
好文集合: 深入浅出React(四):虚拟DOM Diff算法解析 全面理解虚拟DOM,实现虚拟DOM
随机推荐
- unity3d开发的android应用中增加AD系统的详细步骤
unity3d开发的android应用中增加AD系统的详细步骤 博客分类: Unity3d unity3d Unity3d已经支持android,怎样在程序里增加admob? 试了一下,确实能够, ...
- 虚拟机和主机ping不通,SQL Server无法远程连接的解决方法
一.虚拟机网络的配置 这里只列一下自己的配置: 1.编辑---虚拟网络编辑器 进行设置 2.设置对应系统 3.还是Ping不通,最后关闭 虚机内的Windows防火墙,可以Ping通,看来Net模式下 ...
- EasyDarwin云存储方案调研:海康萤石云采用的是MPEG-PS打包的方式进行的存储
EasyDarwin开源流媒体服务器项目在直播功能稳定和完善之后,开始涉及服务器端存储与回放功能的调研与开发,当然,这里就要研究一下行业标杆萤石云是怎么来做的,我们通过非常复杂的流程将萤石存储的录像文 ...
- Spring mvc接受集合类型参数的方法
public String xxxxx(String xxxx, String xxxxx, @RequestParam("parameterList[]") List<St ...
- Intellij IDEA 修改代码后自动编译更新
Intellij IDEA 一些不为人知的技巧 问题描述: Intellij IDEA 调试修改时,改动页面和 java 文件后,无法立刻看到变化,需要手动重启服务. 问题原因: 在 IDEA tom ...
- jquery特效(6)—判断复选框是否选中进行答题提示
前面有一段时间思想开了小差,跟着师父学习了一段时间才发现差距很大,看来我要奋起直追~\(≧▽≦)/~啦啦啦. 最近公司在做一个项目,需要根据用户选择的选项给出相应的提示,下面来看我写的测试程序的效果: ...
- HDU4045 Machine scheduling —— 隔板法 + 第二类斯特林数
题目链接:https://vjudge.net/problem/HDU-4045 Machine scheduling Time Limit: 5000/2000 MS (Java/Others) ...
- CentOS6.3安装 Oracle 11g R2
1.设置系统1.1.包需求 11g很人性化了,增加了检查的机制,还有就是不象10g那样在64位下要安装很多的32位包,只需要安装一个gcc-32bit-4.3就OK了.下列表必须要安装:binutil ...
- [ZJOI 2010] 排列计数
[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=2111 [算法] 一种比较好的理解方式是将该序列看成是一棵堆式存储的二叉树 那么问题转 ...
- [HAOI 2010] 计数
[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=2425 [算法] 类似与数位动态规划的思想 , 用组合数学进行简单推导即可 时间复杂度 ...