【翻译搬运】起源引擎(Source)多人模式网络同步模型(Source Multiplayer Networking)【二】

来源:互联网 发布:软件depthmap教程 编辑:程序博客网 时间:2024/06/10 17:05

写在前面

文章的原文很多地方都能找到

我贴一处起源引擎(Source Engine)开发公司Valve Software的网址,其他的我,提供一处steam的。
① V社 VALVE(Dota2、半条命的开发) Source Multiplayer Networking
https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking
② Steam CSGO(Counter-Strike: Global Offensive)Source Multiplayer Networking
http://steamcommunity.com/sharedfiles/filedetails/?id=527313998

也有人做过优秀翻译 【腾讯GAD译馆】 Source引擎多人模式网络同步模型,我只是因为自己注意力涣散觉得文章干涩不写下来就看不动,也请阅读的大家不要用我的渣翻水平做横向对比,取得必要知识信息就好。

找资料途中发现一篇更加准确的翻译https://tieba.baidu.com/p/1819264994 搬运原文地址已不可寻,贴吧排版不是很方便阅读。(所以我的坑还是会填完的~)

正文


索引


概述(第一篇)
基础部分 Basic networking(第一篇)
支持Tickrate修改的服务器 Servers that Support Tickrate(本篇)
实例平滑插值 Entity interpolation(本篇)
客户端输入预测 Input prediction(本篇)
服务器滞后补偿 Lag compensation(第三篇)
网络状态视图 Net graph(第三篇)
优化 Optimizations(第三篇)
参阅 See also(第三篇)



支持Tickrate修改的服务器 Servers that Support Tickrate

这一小节完全可以略过

The tickrate can be altered by using the -tickrate parameter
- Counter Strike: Global Offensive
- Half-Life 2: Deathmatch

Tick的频率可以通过 -tickrate 命令修改的
- 反恐精英:全球攻势(CS:GO)
- 半条命2:死亡竞赛

The following servers tickrate cannot be altered as changing this causes server timing issues.

- Tickrate 66
- Counter Strike: Source
- Day of Defeat: Source
- Team Fortress 2

- Tickrate 30
- Left 4 Dead
- Left 4 Dead 2

下面这些服务器的Tick频率,因为服务器方面的影响不能改变

固定Tick频率66
- 反恐精英:起源
- 胜利之日:起源
- 军团要塞 2

固定Tick频率30
- 求生之路
- 求生之路 2



平滑插值 Entity interpolation

Paragraph 1

By default, the client receives about 20 snapshot per second.
通常情况下,客户端每秒大约接受20个snapshot

If the objects (entities) in the world were only rendered at the positions received by the server, moving objects and animation would look choppy and jittery.
如果游戏世界中的实体,根据从服务器接受的数据直接渲染出来,那么运动和动画将会表现的十分不平滑。

Dropped packets would also cause noticeable glitches.
丢包也会造成明显的问题。

The trick to solve this problem is to go back in time for rendering, so positions and animations can be continuously interpolated between two recently received snapshots.
解决这个问题的关键,在于滞后渲染。这样位置和动画可以在两个最接近的snapshot之中进行插值。

With 20 snapshots per second, a new update arrives about every 50 milliseconds.
如果每秒接收20个snapshot,也就是每50ms会收到一个新的更新。

If the client render time is shifted back by 50 milliseconds, entities can be always interpolated between the last received snapshot and the snapshot before that.
如果客户端的渲染时间点推延50ms,实体就可以一直在上一个与上上一个snapshot之间做平滑插值。

Paragraph 2

Source defaults to an interpolation period (‘lerp’) of 100-milliseconds (cl_interp 0.1);
Source引擎默认的插值周期(lerp)是100ms(cl_interp值为 0.1)

this way, even if one snapshot is lost, there are always two valid snapshots to interpolate between.
这种放下下,即使是一个snapshot发生丢失,依旧有两个有效的snapshot可供插值。

Take a look at the following figure showing the arrival times of incoming world snapshots:
下图就是输入到客户端的snapshot的时间轴图示:

这里写图片描述

这里写图片描述

【额外说明】关于编号,此图中编号的来历猜测。
首先,说明强调的是,tick的频率和snapshot的频率并不在同一个频率上。虽然图中一一对应,但是意义在于利用xxtick给snapshot的顺序带来一个编号。
所以,下面译文中我使用的说明是tick xxx的snapshot。
最后,关于数值的猜测,简单做个除法 10.15s = 10150ms, 10150/338 = 30(ms),所以是约30ms一次tick,50ms一次snapshot接收。

The last snapshot received on the client was at tick 344 or 10.30 seconds.
最后一个snapshot接收于tick 344或者说是10.30秒。

The client time continues to increase based on this snapshot and the client frame rate.
客户端时间根据这个snapshot和客户端自己的帧率而增加。

If a new video frame is rendered, the rendering time is the current client time 10.32 minus the view interpolation delay of 0.1 seconds.
在我们的例子中,如果此刻要进行新一帧的渲染,那么渲染的取插值的时间点,是从当前时间10.32s减去插值延迟时间段0.1s。

This would be 10.22 in our example and all entities and their animations are interpolated using the correct fraction between snapshot 340 and 342.
也就是(渲染第)10.22s,所有的实例,以及实例上的动画,将要使用tick 340 的snapshot 和 tick 342的snapshot 的平滑插值计算出的值。

Paragraph 3

Since we have an interpolation delay of 100 milliseconds, the interpolation would even work if snapshot 342 were missing due to packet loss.Then the interpolation could use snapshots 340 and 344.
因为我们使用了100ms的插值推延,所以就算tick 342的snapshot 因为丢包而遗失的情况之下,也可以正常工作。插值使用的是tick 340 的snapshot 和 tick 344的snapshot

If more than one snapshot in a row is dropped, interpolation can’t work perfectly because it runs out of snapshots in the history buffer.
如果连续snapshot中丢失大于一个,那么历史缓存的snapshots用尽,插值就不能完美的工作了。

In that case the renderer uses extrapolation (cl_extrapolate 1) and tries a simple linear extrapolation of entities based on their known history so far.
这种情况下,渲染逻辑将使用推断(cl_extrapolate 1【个人推测】 cl_extrapolate = 1 是Source引擎使能推断从功能的开关),根据目前已知的历史,进行一个线性的推断。

The extrapolation is done only for 0.25 seconds of packet loss (cl_extrapolate_amount), since the prediction errors would become too big after that.
但是推断只持续0.25s(cl_extrapolate_amount),更长时间的推断将会使得偏差变得太大。

Paragraph 4

Entity interpolation causes a constant view “lag” of 100 milliseconds by default (cl_interp 0.1), even if you’re playing on a listenserver (server and client on the same machine).
实例插值引起一个默认恒定100ms(cl_interp 0.1)的“延迟”,即使使用监听服务器(客户端和服务器是同一台机器),也是同样。

This doesn’t mean you have to lead your aiming when shooting at other players since the server-side lag compensation knows about client entity interpolation and corrects this error.
这并不意味着玩家需要在设计的时候进行预瞄准,因为服务器端知晓客户端的实例插值,进行滞后补偿来修正这个错误。

Tip: More recent Source games have the cl_interp_ratio cvar. With this you can easily and safely decrease the interpolation period by setting cl_interp to 0, then increasing the value of cl_updaterate (the useful limit of which depends on server tickrate). You can check your final lerp with net_graph 1.
Tips: 最近很多使用Source的游戏支持cl_interp_ratio。这样你可以安全简单的设置 cl_interp到0,来减少插补周期(延迟的时间),然后增加cl_updaterate(上限取决于服务器的tickrate) 。你可以使用net_graph 1来查看最终插值周期。

Note: If you turn on sv_showhitboxes (not available in Source 2009) you will see player hitboxes drawn in server time, meaning they are ahead of the rendered player model by the lerp period. This is perfectly normal!
Note:如果你打开了sv_showhitboxes(Source 2009并不支持),你可以看到以服务器时间绘制的玩家有效射击区,可以看到他们(绘制的有效射击区)在玩家绘制模型的前面,因为有插值的存在,这是完全正确的。



客户端输入预测 Input prediction

Paragraph 1

Lets assume a player has a network latency of 150 milliseconds and starts to move forward.
我们假设玩家有150ms的网络延迟,并且向面向方向移动。

he information that the +FORWARD key is pressed is stored in a user command and send to the server.
这个玩家的 “forward 键值被按下”的消息被填充到玩家指令当中,并且发送给服务器。

There the user command is processed by the movement code and the player’s character is moved forward in the game world.
在服务器端,用户指令由移动代码处理,玩家的角色在模拟的游戏世界里向前移动。

This world state change is transmitted to all clients with the next snapshot update.
在下一个snapshot更新的时候,将这个世界所发生的状态变化,传送给所有的客户端。

So the player would see his own change of movement with a 150 milliseconds delay after he started walking.
所以,玩家可以在自己开始移动的150ms延迟后,见到自己的移动变化。

This delay applies to all players actions like movement, shooting weapons, etc. and becomes worse with higher latencies.
这种延迟对于玩家的行走、武器射击等行动都是存在的,而且对于高延迟的玩家,延迟更为严重。

Paragraph 2

A delay between player input and corresponding visual feedback creates a strange, unnatural feeling and makes it hard to move or aim precisely.
这种玩家输入与相应视觉反馈的延迟感,造成一种奇怪、不自然的感受,并且给移动和精准瞄准造成了难度。

Client-side input prediction (cl_predict 1) is a way to remove this delay and let the player’s actions feel more instant.
客户端的一侧可以使用输入预测法(cl_predict 1) 来消除这个延迟,让玩家的行为反馈感觉更即刻。

Instead of waiting for the server to update your own position, the local client just predicts the results of its own user commands.
不同于等待服务器的更新来更新自己的位置,客户端本地可以预测自己的命令结果。

Therefore, the client runs exactly the same code and rules the server will use to process the user commands.
所以,客户端要与服务器使用同样的代码和规则来处理用户指令。

After the prediction is finished, the local player will move instantly to the new location while the server still sees him at the old place.
预测完成后,玩家本地将会看到角色直接移动到了新的位置,而服务器上的玩家依旧在老的地方(玩家命令执行前)。

Paragraph 3

After 150 milliseconds, the client will receive the server snapshot that contains the changes based on the user command he predicted earlier.
在150ms以后,客户端将收到服务器发送的,包含了刚才进行预测用户指令运行结果的snapshot

Then the client compares the server position with his predicted position. If they are different, a prediction error has occurred.
收到后,客户端将自己的预测结果与服务器结果做对比。如果不同,那么就是发生了预测错误。

This indicates that the client didn’t have the correct information about other entities and the environment when it processed the user command.
这是因为,客户端并没有持有当前(预测Commond运行情况的时刻)游戏世界中的实例信息、环境信息。

Then the client has to correct its own position, since the server has final authority over client-side prediction.
这种情况,客户端需要修正自己的位置,服务器的执行结果的优先级是高于客户端自己预测结果的。

If cl_showerror 1 is turned on, clients can see when prediction errors happen.
如果cl_showerror置为1(开关打开),客户端将会看到预测错误的信息。

Prediction error correction can be quite noticeable and may cause the client’s view to jump erratically.
预测错误的修正,会十分显眼,并且可能会引起画面的跳跃。

By gradually correcting this error over a short amount of time (cl_smoothtime), errors can be smoothly corrected. Prediction error smoothing can be turned off with cl_smooth 0.
想要平滑的修复预测错误,可以使用一小段时间(cl_smoothtime【个人推测】 设置平滑修复的时长)逐步来修正。平滑修正可以通过cl_smooth设置为0来关闭。

Paragraph 4

Prediction is only possible for the local player and entities affected only by him, since prediction works by using the client’s keypresses to make a “best guess” of where the player will end up.
因为客户端预测这个行为,是使用客户端的键位输入做一个“最佳猜测”来决定玩家的结束时的位置, 预测仅仅对玩家本身以及玩家影响的实例才可行。

Predicting other players would require literally predicting the future with no data, since there’s no way to instantaneously get keypresses from them.
对于获取不到当前按键信息的其他玩家,没有这些数据,是不可能实现预测的。

写在后面

第一篇:【翻译搬运】Source引擎多人模式网络同步模型(Source Multiplayer Networking)【一】
第三篇:【翻译搬运】Source引擎多人模式网络同步模型(Source Multiplayer Networking)【三】

欢迎纠错

转载请注明,出自喵喵丸的博客 http://blog.csdn.net/u011643833/article/details/77848012

阅读全文
0 0
原创粉丝点击