Archive

Archive for the ‘游戏开发’ Category

帧同步游戏中使用 Run-Ahead 隐藏输入延迟

October 22nd, 2023 3 comments

帧同步可以轻松解决高互动的联网游戏(如格斗,RTS 等)的同步问题,但该方案对延迟很敏感,现在一般省内服务器延迟差不多 10-15ms (1帧),跨省一般 40ms (2-3 帧),在此情况下,使用 Run-Ahead 机制可以有效的掩盖延迟的体感,让用玩家立马看到自己的操作反馈。

该机制有很多其他名字比如:预测回滚(prediction and rollback),或者时间曲力(time warp),名字取的天花乱坠的,很多文章也只是云里雾里说一半天,结果还没说清楚,所以本文打算最简短的句子说清楚这个概念,并给出可以实际操作的实现步骤。

我觉得用 Run-Ahead 这个质朴的名字更容易说明这个算法背后的思想:提前运行,这个概念不光用在游戏同步里,也早已用在游戏模拟器中,为了便于理解,先说一下模拟器中的情况(更简单)。

RetroArch 使用 Run-Ahead 隐藏输入延迟,一般需要设置一下 Run-Ahead 的帧数,比如 0 是关闭,1 是提前运行一帧,2 是提前运行两帧,一般设置用 1 或者 2,不要超过 5,因为太高游戏表现会很奇怪:

运行时 RetroArch 为每帧保存快照,假定的是用户输入有持续性,那么运行时当前帧使用上一帧用户的输入作为本帧输入(假设 runahead 设置为 1),然后接着往下运行,如果用户新输入来了,一律把它算作当前帧-1 的输入,然后再去对比历史如果和上一帧所尝试假定的输入一致就继续,否则快照回退到上一帧,重新用新的输入去运行,然后再快进到当前帧。

通常手柄或键盘都有 5ms 左右的输入延迟(部分设备如 switch 的 pro 手柄延迟高达 15ms),再加上操作系统处理的延迟,投递到模拟器进程里,从按下到真正开始处理也许也差不多 1 帧的时间了,RetroArch 用这个功能,也只有用户真实输入和预测输入不一致时才会触发,由于间隔很短,所以即使纠正也难看出来,最终在模拟器上达到了物理设备一样的超低延迟体验。

理解了模拟器的 Run-Ahead 实现,其实在帧同步里的原理也就差不多了,无外乎是用远程的旧输入,搭配本地刚采集到的新输入,作为预测帧的输入值,产生新帧,不匹配了再回滚。

帧同步里引入类似 Run-Ahead 的机制,要求游戏最近所有状态都可以被快速保存、复制和恢复,实现有很多种,你可以用状态的反复前进、后退来实现,但是 BUG 率太高了,这里给出一个更简易的实现方式:

(点击 more 展开)

Read more…

Categories: 游戏开发 Tags:

互联网技术比游戏后端技术领先十年吗?

May 20th, 2023 2 comments

最近时间线上又起了一场不大不小的论战,做互联网的人觉得游戏服务端发展很慢,同时互联网技术日新月异,似乎觉得互联网技术领先了游戏后端技术十年,这个结论显然是武断的,几位朋友也已经驳斥的很充分了,游戏服务端的同学实属没必要和这个互联网的人一般见识,本来就此打住也还挺好。

但最近两天事情似乎正在悄悄起变化,时间线上一直看到不停的有人跳出来,清一色的全在说互联网简单,什么做个电商不过就是 CRUD 的话也出来了,看的我也大跌眼镜,过犹不及吧。

今天更是又刷到有几位不管不顾就说什么游戏服务端领先互联网十年什么的,似乎这又要成为了另外一个极端了,那么有几点情况是不是也请正视一下:

1)游戏服务端足够复杂,但是发展太慢,祖传代码修修补补跑个十多年的不要太多。能用固然是好事,但没有新观念的引入,导致可用性和开发效率一直没有太多提升。

2)各自闭门造车,没有形成行业标准与合力,这个项目的代码,很难在另一个项目共享,相互之间缺少支持和协同。

3)互联网后端随便拎出一个服务来(包括各种 C/C++ 基建)大概率都没有游戏服务端复杂,但最近十年日新月异,形成了很强的互相组合互相增强的态势。

我上面指的是互联网基建项目,不是互联网 CRUD,互联网近十年的发展,让其整体可用性,效能,开发效率,都上了很多个台阶,不应一味忽视。

如果继续觉得游戏服务端领先互联网十年可以直接右转了,开放心态的话我也可以多聊一些(点击下方 more 阅读更多):

Read more…

Categories: 游戏开发, 网络编程 Tags: , ,

《原神》也在使用 KCP 加速游戏消息

November 8th, 2022 No comments

最近看到米哈游《原神》的客户端安装文件里附带了 KCP 的 LICENSE:

于是找米哈游的同学求证了一下,果然他们在游戏里使用 KCP 来保证游戏消息可以以较低的延迟进行传输,这里还有一篇文章分析了原神使用 KCP 的具体细节:

文章见:https://forum.ragezone.com/f861/genshin-impact-private-server-1191004/index7.html

KCP 是我之前开源的一套低延迟可靠传输协议,能够有比 TCP/QUIC 更快的端到端传输效果,适合游戏、音视频以及各类延迟敏感的应用。

欢迎大家尝试:

目前使用 KCP 的商用项目包括不限于:

  • 原神:米哈游的《原神》使用 KCP 降低游戏消息的传输耗时,提升操作的体验。
  • SpatialOS: 大型多人分布式游戏服务端引擎,BigWorld 的后继者,使用 KCP 加速数据传输。
  • 西山居:使用 KCP 进行游戏数据加速。
  • CC:网易 CC 使用 kcp 加速视频推流,有效提高流畅性
  • BOBO:网易 BOBO 使用 kcp 加速主播推流
  • UU:网易 UU 加速器使用 KCP/KCPTUN 经行远程传输加速。
  • 阿里云:阿里云的视频传输加速服务 GRTN 使用 KCP 进行音视频数据传输优化。
  • 云帆加速:使用 KCP 加速文件传输和视频推流,优化了台湾主播推流的流畅度。
  • 明日帝国:Game K17 的 《明日帝国》,使用 KCP 加速游戏消息,让全球玩家流畅联网
  • 仙灵大作战:4399 的 MOBA游戏,使用 KCP 优化游戏同步

KCP 成功的运行在多个用户规模上亿的项目上,为他们提供了更加灵敏和丝滑网络体验。

Categories: 游戏开发, 网络编程 Tags:

网游通信协议如何防止封包篡改?

February 20th, 2022 1 comment

第一层:协议非对称加密交换密钥,对称加密传输内容,保护好服务端私钥,防止中间人攻击。流式加密,同样包发两次内容不一样。

第二层:不用标准序列化工具如 protocolbuf,用修改版或者自己实现的。

第三层:客户端加密加壳防止调试和注入,程序签名防止篡改二进制。

第四层:重要代码放虚拟机或者脚本里运行(脚本字节码需需改),一般黑客主要分析反汇编,你复杂逻辑多套几层他就晕了。

第五层:关键数据不落内存,一律使用 getxx,setxx 之类的接口,后面将真实数据经过变换以后才落内存。

第六层:守护进程动态跟踪监控情况。

第七层:决定性逻辑永远放在服务端。

第八层:服务端定期校验消息合理性,比如十秒内最大的移动步长是多少,实际发上来的合理不合理,不合理就踢掉,比如按键点击频率是否超过正常人。

第九层:不定期弹出反外挂答题,答正确奖励经验,错误就掉线。

第十层:必须要放在客户端计算的内容将输入和结果 hash 同步给其他客户端验算,不对就踢掉。

第十一层:当检测到客户端触碰到某规则不要急着踢掉它,而是有概率被踢掉,还要随机几秒踢掉,这样黑客发现一会这里断一会那里断,就蒙圈了。

第十二层:发现某黑客/外挂工具利用某漏洞破解了游戏,先看影响大不大,再看他挣不挣钱,影响一般又不挣钱的话可以先养着他,等他挣钱了用户多了,大型活动之前,一条指令就把它封了,用户退款都可以弄得他爬不起来。

。。。。。

手机打字慢,先写这些,没有绝对安全,就是合理的策略加攻防成本。

Categories: 游戏开发 Tags:

如何实现一款 1KB 大小的空战游戏?

October 9th, 2020 No comments

经常看到知乎上有人在问:那些只有几 KB 的游戏是如何制作出来的?刚好这种代码我也写过,1KB 大小的空战游戏,很久以前读书时写的:

WINXP 下(或者 DOSBOX)在 DOS 窗口中运行 DEBUG,然后把横线下的内容复制、粘贴到 DEBUG 窗口中,回车就可以见到了。

(点击 Read more 展开)

Read more…

Categories: 游戏开发 Tags:

关于 “帧同步” 说法的历史由来

August 2nd, 2020 No comments

关于游戏同步的话题说的太多了,我是不想再谈了,但是碰到一些含糊和容易引起混淆的地方,必须澄清一下,云风在 2018 年在《lockstep 网络游戏同步方案》中有一段:

首先,我认为把 lockstep 翻译成帧同步,还有与之对应的所谓“状态同步” (我在多次面试中听过这个名词),都是对同步算法的错误理解造成的。把自己所理解的算法牵强附会到已有的在欧美游戏先行者中经过实践的方案上。

最近网易雷火工作室的一篇文章《细谈网络同步在游戏历史中的发展变化》谈到了类似的观点,那么为了避免产生混乱,有必要对 “帧同步”这个说法做一次澄清。

帧同步不是单指某个具体算法,而是范指 “保证每帧(逻辑帧)输入一致” 的一系列算法,传统实现有帧锁定,乐观帧锁定,lockstep,bucket 同步等等,但凡满足“每帧输入一致”的方法皆可以归纳为帧同步类别,至于要不要回滚?服务端要不要跑一套完整逻辑?操作要不要是键盘鼠标?还是高阶命令?客户端要不要像视频播放器一样保证平滑缓存 1-2 帧?或者要不要保证平滑加一层显示对象的坐标插值?这些都是具体优化手段。

我在 2009 年公司应届生培训的《服务端开发培训》课程内,最早开始做同步技术培训:

这个 “帧间同步”喊着喊着就被喊成了“帧同步”,这应届生培训持续了好几年,应该数百人听过这个课程,后面的讲师又接着迭代这个 ppt 接着讲了好几年,听过的应届生们自己摸索后,又写了新的技术分享放到网上,兴许从那时候 “帧同步”和 “状态同步”的说法就流传开了吧。

(点击 Read more 展开)

Read more…

Categories: 游戏开发 Tags:

游戏机模拟器的具体原理是什么?

February 8th, 2017 1 comment

“游戏机模拟器” 注重的是 “严格模拟硬件”,要精确,可以对照 MAME代码,所有问题都能在里面找到对应答案:

第一:模拟 CPU

MAME里实现了各种 68000, z80,mips, sparc, arm,pic16c5x,nec, alpha,等 100 多款你见过的或者没见过的主从协处理器的模拟,虽然都是 switch case opcode,但是不像 lua虚拟机。MAME的 CPU模拟重点在 “精确实现硬件”,除了指令集实现外,还有各种软硬终端/trap/异常处理/IO实现。举个简单例子,一个游戏主机需要 4MHz 的 z80芯片,你就得给我真的按照 4Mhz来跑,每条指令计算周期,不能多也不能少,你要把 4Mhz跑成 8Mhz,游戏玩起来节奏就不一样了。比如以前老游戏机上敌人一多,就会慢下来,你实现模拟器,也得把这种慢下来给实现了。另外很多街机是双处理器,比如一块 68000 + z80,你不能复原老主机的运行速度,一些写的粗糙的游戏 ROM可能会出错。

模拟 CPU重点是 “精细”,比如浮点数误差最好一致,比如中断优先级你得模拟出来,模拟器由于按照 interval 来运行,更容易产生同时多个硬件中断被触发,比如 “手柄按键” ,多核通信之类各种东西加在一起,某个核满负荷运行的情况下,优先级低的可能永远得不到处理,弄错了可能游戏就没法玩了。

第二:模拟总线

总线也有好多规格需要实现,不同基板的总线链接不同cpu 和外设的方式都不一样,还是需要 “精确模拟”,比如 ROM /RAM / IO 地址映射,一些大容量游戏需要 ROM 的 BANK 切换,还有一些游戏会在卡带上带有扩展内存,除此之外还要正确模拟各种异常,比如某些 RAM,读写奇数地址会出错,要给对应 CPU发送异常信号,某些老点的 RAM只能读写 16bit的 WORD,不能读写 DWORD或者 BYTE,否则都无效。这些你都得模拟到位了,有些有 BUG的游戏,错误的写了内存,在真实主机上,写操作直接被硬件忽略掉了,没有损伤,但软件模拟不注意执行了那条指令结果就不一致了。

第三:外设模拟

音频芯片,I/O,图形加速芯片,随机数发生器,音视频输出,摇杆,时钟等。有些外设是有bug的,你也要把这些历史上的硬件bug给模拟进去,不然游戏可能行为不一致。

第四:调试系统

提供终端和接口可以内存 DUMP,反汇编,修改指令和数据,保存现场之类的。

有史以来出现过的游戏机硬件数不胜数,但是他们用到的芯片或者硬件是有限的,比如z80和 68000这类流行的芯片,具体每台主机其实就是一份配置文件,包含使用那种总线,哪些cpu,分别按照什么速度来运行,内存I/O布局,关联哪些外设,BIOS和启动加载等信息。

总之是个辛苦活,你需要一本硬件手册,然后边查边弄。

如果你嫌 MAME太复杂庞大,再推荐一个 gens 的代码,只针对世嘉16位机的 Windows实现,条理很清晰,很多比世嘉简单的 FC模拟器写的都没有 gens那么结构清晰,简单易读。它就不像MAME那么大而全,很多步骤实现的很直接不需要配置那么多,代码量也不大。

现在新进的模拟器很多,没机会逐一查看他们的实现细节,只记得有几款比较新的模拟器都是直接裁剪 MAME的部分代码来弄的,因为 MAME里面几乎实现了所有游戏能用的芯片了,拿出来改改参数加点指令集就可以用,比如 MAME里面模拟了 mips,我们裁剪出来实现 PSP模拟器,个别指令有些区别需要改一下,然后我们着重自己实现 PSP里面 MAME没有的硬件部分。

Categories: 游戏开发 Tags:

再谈网游同步技术

May 9th, 2015 18 comments

实时动作游戏在近年来得到迅猛的发展。而游戏同步问题,成为大家继续解决的核心问题之一。早在 2004年,国内游戏开发还处于慢节奏 RPG满天飞的情况下,我就开始实时动作游戏研究,分别在 2005-2006期间写了一系列相关文章,被好多网站转载:

帧间同步模式:《帧锁定同步算法》(2007): https://www.skywind.me/blog/archives/131 

玩法规避模式:《网络游戏同步法则》(2005): https://www.skywind.me/blog/archives/112

预测插值模式:《影子跟随算法》(2007): https://www.skywind.me/blog/archives/1145

如今十年过去,网上越来越多的人开始讨论游戏同步技术了,然而很多文章往往只针对某种特定的游戏情况,而观点又经常以偏概全。很多人并没有真正开发过实时动作游戏,更别说了解同步技术的前世今生了。转载别人的观点并加上自己理解的人很多,实际动过手的人很少。避免给更多人造成无谓的误导,我今天基于先前的实践和对欧美动作游戏,战网游戏,主机游戏(PSN,XBox Live等)网络技术的了解,来对这个问题做一个简单总结:

网速的变化

开发快速动作游戏,首先要对公网的网络质量数据有详细的了解。这里所说到的网速,是指 RTT,数据往返一周的毫秒时间,而非每秒传送多少 KB/s。我写这篇文章是基于我 2005-2006年开发的东西来说的,当时国内公网质量比国外差很多:

clip_image003

上图为 2005-2006年国内的网络环境,某三个省级 IDC的情况采样。当时公网 RTT平均值基本在100ms,120ms左右徘徊。所以我文中引用了很多 100ms。这个情况在2009 年以后已经好了很多(60ms的rtt)。到了2012年以后,公网平均 RTT已经降低到平均 40ms-50ms,省内平均10ms以内了:

image

上图为 2015年某省级 IDC的全国延迟情况,如若全国多布点以及区别电信联通的话,平均延迟能控制在20ms以内,延迟基本接近国外水平(当然带宽还差很多),比我当年文章中提到的网络情况好了不少。

Read more…

Categories: 游戏开发, 网络编程 Tags: ,
Wordpress Social Share Plugin powered by Ultimatelysocial