游戏邦在:
杂志专栏:
gamerboom.com订阅到鲜果订阅到抓虾google reader订阅到有道订阅到QQ邮箱订阅到帮看

分享《Roblox》扩展物理引擎的方法

发布时间:2012-07-19 18:01:56 Tags:,,,,

作者: Kevin He

[前暴雪网络游戏《Roblox》的物理和网络工作主管Kevin He通过本文分享了如何在建造游戏中支持数百万玩家同时模拟刚体,且不损失表现或乐趣。]

《Roblox》以一个全面的物理引擎为建立基础,支持数百万用户不断地产生内容,从而将其能力拓展至极限。为了使我们的用户能够发挥他们无尽的创造力,释放他们对越来越庞大和复杂的模拟系统的热情,我们决定不断优化物理引擎。

在《Roblox》中,我们模拟了所有刚体物理现象(游戏邦注:在物理学中,刚体是理想化的立体,在受到外力的情况下形状和大小,也就是刚体上的任意两点的距离都不发生变化),因为我们的用户是以砖块、积木、楔形、球体和圆柱体为基础制作游戏的。这些元素在游戏中的表现与真实世界中的一样,这就减少了学习难度,使用户得以创造几乎任何类型的游戏,同时增加了创意性——2011年注册的用户在游戏中逗留时间达到了2亿5千万个小时,这要归功于成功的刚体物理模拟系统。

我们应该注意到,复杂的物理模拟并不会让游戏变得多好,很多时候那只是浪费资源。其实,物理引擎的复杂性应该与游戏玩法的要求相一致。

《Roblox》的物理学

在游戏中,如果将物理复杂度从难到易排列,那么《Roblox》位于这个频谱的困难极端。而另一个极端是MMORPG(例如《无尽的任务》、《魔兽世界》等游戏)——它们用基本的碰撞检测(游戏邦注:碰撞检测一般是指检测两个或多个对象的交集情况,多用于电子游戏或其他物理现象的模拟)保证将玩家限制在可游戏区域中。

第一人称射击游戏(如《光晕》)和动作RPG(如《暗黑3》)使用的碰撞检还稍微先进一些,支持接触力和有限的碰撞形状(如胶囊体)来产生碰撞反应。它们还将角色置于“被动的”布娃娃状态(游戏邦注:在电脑物理引擎中,布娃娃是指由某个限制角色骨骼相对运动情况的系统捆绑在一起的一系列多个刚体),死亡时就倒下,爆炸时就飞起来;并利用“装饰性”布娃娃——如移动头发来增加画面动态。

说到运动,物理模拟就开始变得有趣而复杂了。除了在MMORPG和动作游戏中可以看到的所有东西,如《拳击之夜4》和《FIFA 12》等运动游戏还引入“主动的”布娃娃,使运动肌能支撑斗士和玩家角色的关节运动。这就使角色实现顺畅平滑、栩栩如生的动作和动画。如果没有运动肌,斗士和玩家角色的四肢将会了无生气地悬挂着,然后摊倒在地。

最后,在《Roblox》中,全面物理引擎是默认开启的,而关闭则是可选项。所有物理对象(地形除外)——都是模拟的。我们的引擎具有以下特点:

1、碰撞检测支持接触力和一系列丰富的碰撞形状,包括盒状、球体、圆柱体、楔形、多边形等。

2、完整刚体动力学,将所有相关力(重力、接触力、摩擦力、弹力、浮力、粘性和运动物体力)整合在一个传递途径中。

3、基于物理学的角色动画,“被动的”和“主动的”布娃娃,站立、奔跑、跳跃、落下和游泳的平衡控制器。

4、机械工具和船只,以一系列丰富的连接类型,如活动的、铰链、焊接、绳索、棱柱、旋转、机动等等。

5、浮力和高级水物理

以上模拟也必须在多人网络环境中执行。

从分立到聚合的物理

给某人一堆积木,他可能会尽量多地使用积木制作一个庞然大物。《Roblox》也不例外,但将摩天大楼的每一个独立部分,或泰坦尼克号作为一个个体——或分立的刚体来模拟,就会占用太多的网络和CPU/GPU资源。

在模拟大型建筑和交通工具方面,我们的处理办法很巧妙。当摩天大楼固定到地面时,我们就将它当作一个嵌在背景环境中的单一整体。各个分立砖块都不发生动态活动,只有碰撞检测在摩天大楼和其他移动部分或结构之间执行。我们的引擎将整个摩天大楼压缩成一个静态、轻量型的部分,因此它只消费少量内存。“轻量型”使《Roblox》世界得以用最少的成本容纳成千上万个复杂的建筑。

至于在水中航行的泰坦尼克号,为了模拟真实的浮动效果、与水体的相互作用以及与其他的漂浮物的碰撞,整艘船必须在我们的刚体动态引擎中运行。把船只的各个部分作为独立的刚体来模拟太占资源,所以《Roblox》将如此大体积、焊接刚体模拟成一个高效的集合,便于在物理模拟时管理资源。

在运动框架中,《Roblox》能动态地识别不移动的、彼此关联的对象对子。它将这类对象归类,产生集合。甚至由上千个部分焊接在一起的泰坦尼克号也被模拟成单个刚体。这就是我们将物理模拟分割成上百万个部件时必需实现的效能。

图1(from gamasutra)

图1(from gamasutra)

(图1在这个场景中,有两个来自同一集合的部件,在动态框架中,他们不移动,彼此关联。)

集合不是最高明的办法,因为执行时会产生一系列难题。在一个存在不断活动、碰撞、爆炸和人类互动的动态环境中,集合会不断地成形、破碎,合并。以下是一些常见的例子:

1、粘合在一起的不同部分会因足够的分离力而破裂。

2、当一个部件的表面入口与另一个部件的表面入口接触时,原本分离的物体会结合在一起。

3、拟人角色被杀死或被刀剑砍伤时会被撕裂,因为关节断裂。

4、用户可以用LUA脚本语言动态地插入或移除两个部件之间的关联,由此破坏或合并集合。

在客户端和服务器之间,当这些改变发生时,我们的引擎必须即时地使集合的组成部分始终保持同步。我们在集合中挑选相同的根体,并且以相同的顺序在客户端和服务器边界生成这些根体,以实现顺畅的网络运动。

从集中到分散的物理

利用集合,我们从集中物理转换到分散物理,这就允许更多的玩家和更多的物理模拟进入共享空间。《Roblox》最初使用集中物理模拟,即在游戏服务器上处理物理计算的模式,然后将其结果不断地反馈给玩家,并呈现在屏幕上。

当小规模运作集中模式时,也就是少量玩家、少量物理模拟或少量模拟部件——《Roblox》的执行情况并不能满足我们的发展和越来越复杂的物理要求。服务器必须模拟太多部件和玩家交互作用,导致运动减速,无法即时反应。

在2010年,我们将集中引擎改进为分散的物理引擎,这才解决了这个问题。

图2(from gamasutra)

图2(from gamasutra)

(图2这个图片是分散物理简化模式图。事实上,客户端模拟区域并不一定是相同的形状。)

分散物理在服务器和玩家之间分离物理模拟。在上图中,蓝色区域代表服务器(服务器模拟区域)及其所有物体和玩家。而在集中模式中,当玩家处于某个区域时,由服务器处理物理模拟并向玩家回复数据。

不同点在于,各个玩家都有一个物体的动态区域——它们会进行局部模拟(客户端模拟区域),以减轻服务器的压力。这种分布结构得以让我们在不损失物理表现的情况下,将模拟的物体数量扩大至无限。

我们执行负荷平衡的算法,根据各个玩家的计算机性能和网络带宽,相应地缩小或扩大于各个玩家的区域面积。电脑运行或网络连接慢的玩家一般只能模拟更少的物体;而电脑运行或网络连接快的玩家则相反。分散物理学背后的关键难题是,在两个玩家的模拟区域的边界之间模拟物体。

严格分区作用在非常简单的情形中:例如,一个物体在一个玩家的模拟区域中,并且与其他的物体不存在交互作用。该玩家执行这个刚体模拟,并把结果发送给另一个玩家。

再困难一点的情形,即在一个非常可能发生的场景中,物体A和物体B彼此碰撞。两个物体各位于两个玩家的区域中。理论上说,我们可以让其中一个玩家模拟物体A,而另一个玩家模拟物体B,然后交换模拟结果。随着即时网络的更新,这个方法是可行的。但网络更新的间隔通常(如15Hz)低于维持带宽的渲染速率(如30Hz)。假设我们的物理引擎的在30Hz的速率下模拟,两倍于网络更新频率,但物理模拟每执行一步才产生一次网络更新。这会在高速碰撞时产生问题。

以下是例子:

A是由玩家A模拟的汽车

B是由玩家B模拟的砖块

情形:汽车A驶向砖块B。汽车A反弹回来,就好像它撞上一堵橡皮墙。汽车A应该减速,而砖块B应该至少被撞翻。接下来是解释为什么它破裂了:

模拟A(汽车A|玩家A):

A高速撞上B产生接触力,将A从B上分离开来

A反弹并离开B;发送A的更新给B

A接收来自B的更新;B没有移动

模拟B(物体B|玩家B):

B接收来自A的更新;A与B有两步之遥

A与B有一步之遥遥;发送B的更新给A

B接收来自A的更新。A离开B。B没有移动。

在模拟A处理碰撞并将汽车从砖块上分离开以前,模拟B没有机会目睹碰撞。结果是,砖块B表现得好像它是固定的,而汽车A反弹。

对于慢速碰撞或交叉边界的交互作用,这个情形并不会发生,因为双方都有机会目睹这个互交互作用,并产生更可信的反应。增加网络更新频率或减少网络连接延迟可以优化高速碰撞的结果,但它不能解决的问题是:碰撞中的双方并非由同一个模拟器模拟。

分散物理和缓冲带

《Roblox》在两个玩家的模拟区域之间制造了一个“缓冲带”,解决了交叉边界模拟的问题。位于缓冲带中的物体由双方玩家共同模拟。在刚才的汽车碰撞的例子中,汽车和砖块分别由玩家A和玩家B模拟。汽车A和砖块B都会产生正确的碰撞行为。

当缓冲带被激活,两个玩家模拟相同的物体。一个玩家是“主体”,负责物体的远程物理模拟并且通过服务器向另一个玩家发送数据。另一个玩家是“次体”,负责本地模拟物体以填充所有“主体”产生的数据空隙。《Roblox》协调了远程(实际的)模拟和本地(估计的)模拟之间的运动。

图3(from gamasutra)

图3(from gamasutra)

(图3叠加的红色区域代表共享的缓冲带。位于缓冲带中的物体由双方玩家共同模拟。)

最简单的协调算法会混合来自远程和当地模拟的结果。无论何时,当远程更新进入,我们就改变物体的位置。这个方法可行,但会使快速移动的物体在缓冲带中呈断断续续效果,这是因为远程和本地的模拟结果不相符。

不相符问题与网络延迟情况成等比例发展。通过将模拟物体的速率、位置数据和时间标记(发送和接收时间)整合成各个网络信息包,我们补偿了远程和本地物理模拟之间的网络延迟。来自远程模拟器(在时间t2)的更新如下:

发送时间:t1

位置:x

速率:v

我们补偿网络延迟的方法不是将x(远程位置)直接与本场模拟结果混合,而是计算x如下:

X远程’ = X远程 + (t2 – t1) * v

然后,我们将补偿后的X远程’与本地模拟结果X本地混合。当物体以等速移动时,补偿后的远程和地本模拟之间差异会接近0。当X远程’与X本地的增量非常小时,我们可以用X本地直接传送物体移动的轨迹,而不产生断断续续。

当物体发生碰撞或在速率上经历显著变化,可以抛弃补偿后的远程结果,因为这个速率值很快就过时了。在这种情况下,我们更看重本地模拟结果,使之在碰撞结束或加速趋平时,慢慢取代远程结果。假设从物体受到主要影响开始计算,用去的时间是e,位置x可以在远程和本地模拟之间混合:

当 e < 1:

X = (1 – e) * X本地 + e * X远程’

当 e > 1:

X = X远程’

运用以上公式,我们可以足够精确地计算运动,然后插入两个模拟结果之间,同时使物体不产生断断续续或不自然的移动。

这距离完美还很遥远。我们的未来目标是,在混合分离物理模拟之间的运动算法中加入更多智能。最终,我们希望通过分散物理引擎,将来自成百上千的玩家的模拟结果无缝地联结在一起,创造出一个庞大、连贯、在物理学上精确的世界。

《Roblox》物理的新发展

我们正在不断地扩大规模,使《Roblox》的物理引擎执行和整合新的动力系统。

例如,我们最近在《Roblox》中增加了水体和浮力模拟。我们主要是在空白结构上执行,这样物体和角色在水中的行为看起来和感觉起来都像《Roblox》的物理的自然拓展。这包括将浮力整合进我们的标准物理传递途径;我们将一片水域当作一个物体,通过漂浮物与水之间的接触(或碰撞)将浮力赋予漂浮物。水与漂浮物、漂浮物与漂浮物,以及漂浮物与沉没物之间的碰撞都在统一的引擎中模拟。

我们的结构物也统一了所有力——浮力、水粘性力、水流动力、重力、接触力和其他的外力。漂浮物的运动是所有这些力作用于遵循牛顿定律的刚体的共同结果。

我们还高细节地模拟了水和浮力。例如,想想把一个方块投入水平。因重力作用,方块陷入水中;又因为水的浮力将它推向水面,方块可能会滚动和调整方向。在《Roblox》中,我们把方块分成8个体素(游戏邦注:体素(voxel),是体积元素(volumepixel)的简称;是数字数据在三维空间分割上的最小单位,体素用于三维成像、科学数据与医学影像等领域。概念上类似二维空间的最小单位——像素)以模拟它在水中的方向调整,各个体素都有各自的浮力插入器。

通过将作用于漂浮物(方块、楔形和角落楔形)的浮力分为体素,当稳定后,漂浮物适当地调整自己,对不平均的外力作出准确的反应,例如由站在一个角落的玩家引起的压力。我们还将水沾性力运用于线性和自转的速率,以抑制运动增加真实感。

另一个例子:当我们计算作用于漂浮物的水浮力时,我们高级水物理能够良好地区分交叉和相切表面之间的区域。我们的引擎模拟了机动船桨和水表面之间真实的相互作用,成功地驱动了船只。你可以在演示视频http://www.youtube.com/watch?v=nISvYnB9NbE&feature=youtu.be 中看到薄船比厚船走得更快,尽管二者都有相同的水中陷入体积。船与水中的其他的物体产生交互作用,这是我们对高级水物理和刚体动力学的统一的模拟。

图4(from gamasutra)

图4(from gamasutra)

(图4在《Roblox》中,体素方块的最终方向受到其密度的影响,正如它在现实世界中所表现的。)

我们的水和浮力模拟便利了各种实际应用,从船只建模到真实的水中燃料驱动器。我们已经成功地创造了这些,但相信我们的用户还会发现改进最初设计的方法。

未来的发展

《Roblox》基于全面而真实的物理引擎。它是我们平台的基本组成部分,给游戏玩法和开发带来多种功能和直观性。虽然水和浮力物理代表了重要的进展,因集合和分散物理学的高效而更加便利,我们的目标是继续优化《Roblox》的物理引擎,使之能够支持上百万个部件和成百上千名玩家之间的交互作用。

有了如此先进的物理模拟系统,《Roblox》用户就能够建立任何他们在大型多人游戏、网络世界中要的东西,让梦想与现实交汇。(本文为游戏邦/gamerboom.com编译,拒绝任何不保留版权的转载,如需转载请联系:游戏邦

Scaling a Physics Engine to Millions of Players

by Kevin He

[An ex-Blizzard physics and networking lead for online game Roblox shares the secrets of how the Lego-like building game simulates rigid bodies for millions of players at a time -- without losing either performance or fun.]

Roblox is built on a comprehensive physics engine, and our millions of users are constantly generating content that pushes it to the limits of its capabilities. To enable our users’ unrestrained creativity and cope with their passion for ever-larger and increasingly complex simulations, we’ve committed ourselves to a regimen of physics-engine optimization.

In Roblox, we simulate all rigid-body physics because our users create games on the foundation of bricks, blocks, wedges, spheres and cylinders. These elements behave in game as they would in the real world, which eases the learning curve, makes it possible for users to create games in almost any genre, and adds a layer of discoverability — all contributors to the 250 million hours of gameplay our users logged in 2011.

We should note that complex physics simulation doesn’t make a game good and, in many cases, would be a waste of resources. Instead, the complexity of a physics engine should parallel the gameplay requirements.

Roblox’s Physics, In Context

Roblox is near the extreme end of the physics-complexity spectrum in gaming. On the other end are MMORPGs — from EverQuest to World of Warcraft — which employ basic collision detection to keep players confined to playable areas.

First person shooters, such as Halo, and action RPGs, such as Diablo III, take collision-detection a step further with contact force and limited collision shapes (e.g., capsule) to generate a collision response. They also put characters into a “passive” ragdoll state, sending them tumbling after death or flying after an explosion, and use “decorative” ragdoll — moving hair, for example — to add dynamic visuals.

Sports are where physics simulations start to get interesting and complex. In addition to everything seen in MMORPGs and action games, sports games, such as Fight Night Round 4 and FIFA 12, introduce “active” ragdoll, where motors actually power the joints of the fighters and players. This helps achieve smooth, life-like motion and animation. Without their motors, fighters’ and players’ limbs would hang lifelessly and they’d collapse to the ground.
Finally, there’s Roblox, where full physics simulation is enabled by default, disabled as the exception. All physical objects — terrain excluded — are simulated. Our engine features:

Collision-detection with contact force and a rich set of collision shapes, including box, sphere, cylinder, wedge, convex hull and more
Full rigid-body dynamics, integrating all relevant forces (gravity, contact force, friction, joint/spring force, buoyancy, viscosity and kinematic body force) in one pipeline
Physics-based character animation, “passive” and “active” ragdolls, balance controllers for standing, running, jumping, falling and swimming
Mechanical vehicles and boats, built on a rich set of joint types, including kinematic, hinge, weld, rope, prismatic, revolute, motorized and more
Buoyancy and advanced water physics

These simulations must also perform in a networked, multiplayer environment.

From Discrete to Aggregated Physics

Give someone a set of building blocks and they’re probably going to use as many as possible to create something massive. Roblox is no exception, but simulating every single part of a skyscraper or a Titanic-sized ship as an individual — or “discrete” — rigid body is prohibitively expensive for network and CPU/GPU resources.

We are smart about simulating massive structures and vehicles. When a skyscraper is anchored to the ground and immobile, we treat it as a single entity, attached to the background environment. No dynamic motion is simulated for the discrete bricks and only collision detection is performed between the skyscraper and other moving parts or mechanisms. Our engine compresses the entire skyscraper into a static, “featherweight” part that consumes little memory. “Featherweighting” helps a Roblox world scale to thousands of complex buildings with minimal cost.

For a Titanic-sized ship sailing in water, the entire ship must run in our rigid-body dynamics engine in order to simulate a realistic, floating effect, the interaction with water and collisions with other floating objects. Simulating each of the ship’s thousands of parts as individual rigid bodies would be prohibitively expensive, so Roblox simulates such high-volume, welded rigid bodies as a more efficient “Assembly” to manage resources during physics simulations.

Roblox dynamically identifies pairs of objects that do not move, relative to one another, during a frame of motion. It groups such objects together, creating an Assembly. Even a Titanic-sized ship with a thousand parts welded together is simulated as a single rigid body. This is the kind of efficiency we need to scale our physics simulation to millions of parts.

In this scenario, two parts form an Assembly, as they do not move, relative to one another, during a frame of motion.
Assemblies are not a silver bullet; their implementation presents a unique set of challenges. In a dynamic environment with constant movement, collisions, explosions, and human interactions, Assemblies are formed, fragmented, and merged all the time. Here are some common examples:

Parts glued together can break with enough separation force

Bodies originally separated can be welded together at run time when the “inlet” of a part’s surface touches the “outlet” of a part’s surface

Humanoid characters will be torn apart when killed, even due to a sword strike, because the joints are broken

Users can write LUA scripts to dynamically insert or remove joints between two parts and cause the break-up or merge of Assemblies

Our engine has to synchronize a consistent composition of Assemblies in real time, between clients and servers, while these changes are happening. We select the same root bodies for Assemblies and generate them in the same order across the client and server boundary to achieve smooth networked motion.

From Centralized to Distributed Physics

Along with Assemblies, our shift from centralized to distributed physics has allowed more players and more physics simulations in a shared space. Roblox initially used centralized physics simulation, a model under which physics calculations are processed on the game server, and the results are constantly fed to players and reflected on screen.While a centralized model works on a small scale — meaning few players, few physics calculations or few simulated parts — Roblox’s implementation wasn’t made to stack up against our growth and increasingly complex physics. The server must simulate too many parts and player interactions, causing motion slow down rather than run in real time.We solved this problem by evolving our centralized engine in 2010 to a distributed physics engine.

This graphic is a simplified illustration of the distributed physics model. In practice, client-simulated regions are not necessarily uniform in shape.

Distributed physics distributes the physics simulation among the server and players. In the graphic above, the blue area represents the server (server-simulated region) and all its physical bodies and players. In the case that no player is within an area, the server handles the physics simulation and relays data to players, as in the centralized model.

The difference is that each player has a dynamic region of physical bodies — those within close proximity — that they simulate locally (client-simulated region), taking the strain off the server. Such distributed architecture allows us to scale to an almost infinite number of physically simulated bodies without degrading physics performance.

We implemented load-balancing algorithms to shrink or grow the region size of each player, based on their computation power and network bandwidth. Players with slow machines or internet connections will generally simulate fewer physical objects; the opposite is true for players with fast connections and hefty rigs. The key challenge behind distributed physics is simulating objects at the border of two players’ simulation regions.

A strict division works in very simple circumstances; for example, an object is in one player’s simulation region and not interacting with other objects. The player runs the rigid-body simulation and sends the results to the other players.

In a more challenging — and very likely — scenario, object A and object B are colliding with each other. Each object is in a separate player’s region. Theoretically, we could let one player simulate object A and the other player simulate object B, then exchange simulation results. With an immediate network update, this works. But the network update interval is usually lower (e.g., 15Hz) than the rendering rate (e.g., 30Hz) to conserve bandwidth. Assuming our physics engine simulates at 30Hz, twice as fast as the network update frequency, the network update only occurs at every other step of physics simulation. This causes problems during high-speed collisions.

Here’s an example:

A is a vehicle simulated by player A

B is a brick simulated by player B

The scenario: Vehicle A runs into brick B. Vehicle A bounces back as though it ran into a rubber wall. (We wrote an article about this phenomenon, for more background.) Vehicle A should slow down and brick B should at least get knocked over. The following steps illustrate why it breaks:

Simulation A (Vehicle A/Player A):

A touches B at high speed and generates contact force, separating A from B

A bounces back and moves away from B; sends update of A to B

A receives update from B; B is not moving

Simulation B (Object B/Player B):

B receives update from A; A is two steps away from B

A is one step away from B; sends update of B to A.

B receives update of A. A moves away from B. B is not moving.

Simulation B doesn’t get a chance to witness the collision before Simulation A processes the collision and separates the vehicle from the brick. As a result, brick B behaves as though it was anchored and vehicle A bounces back.

For slow collisions or cross-boundary interactions, this situation does not occur because both sides have a chance to witness the interaction and generate a more believable response. Increasing the network-update frequency or reducing network-link latency will improve the results of high-speed collisions, but will not solve the problem: The two parties involved in a collision are not simulated on the same simulator.

Distributed physics and buffer zones

Roblox addresses the cross-boundary simulation challenge by creating a “buffer zone” between the simulation regions of two players. Objects in the buffer zone are simulated by both players. In our vehicle-collision example, both the vehicle and the brick are simulated by player A and player B. Both vehicle A and brick B will generate correct behavior for the collision, as seen in this demo video.When a buffer zone is active, two players simulate the same physics object(s). One player is the “authority,” meaning they run a remote physics simulation of the object and send the resulting data to other players via the server. The other player is “secondary,” which means they run the physics simulation locally to fill in any data gaps that come from the “authority” player. Robloxblends the motion between the remote (actual) simulation and local (estimated) simulation.
The overlapping red areas represent shared buffer zones. Objects in the buffer zones are simulated by both players.

The simplest blending algorithm interweaves the results from the remote and local simulations. Whenever a remote update comes in, we change the object position. This works, but can cause fast-moving objects in the buffer zone to stutter, due to the discrepancy between remote and local simulation results.

A discrepancy is guaranteed to exist in proportion to the network lag. We compensate for network lag between the remote and local physics simulations by including the velocity, positional data and timestamp (send and receive time) of simulated objects with each network packet. An update from the remote simulator (at time t2) would look like this:

Sending Time: t1

Position: x

Velocity: v

Instead of blending x (remote position) directly with local simulation results, we compensate for network lag by figuring x as:

Xremote’ = Xremote + (t2 – t1) * v

Then, we blend the compensated Xremote’ with the local simulation result Xlocal. The discrepancy between the compensated remote and local simulations will be close to zero when the objects are moving at constant speed. When the delta between Xremote’ and Xlocal is very small, we can use Xlocal directly to render a trajectory of the moving object with no stuttering.

When objects are colliding or experiencing a significant change in velocity, the compensated remote result can be thrown off because the velocity value is quickly outdated. In these situations we give more weight to the local simulation results and gradually fade in remote results as the collision settles or acceleration levels off. Assuming the time elapsed since a major impact on the object is e seconds, the position x can be blended between remote and local simulations as follows:

When e < 1:

X = (1 – e) * Xlocal + e * Xremote’

When e > 1:

X = Xremote’

These formulas allow us to estimate motion accurately enough to interpolate the two simulations without causing objects to stutter or move unnaturally.
This is still far from perfect. Our vision for the future is building more intelligence into the algorithm that blends motion between separate physics simulations. Ultimately, we want to seamlessly stitch together the simulation results from hundreds of players and render a massive, coherent, physically accurate world via the distributed physics engine.

A New Evolution in Roblox Physics

We’re continuously improving the scale at which Roblox’s physics engine performs and integrating new dynamics.

For instance, we recently added water and buoyancy simulation to Roblox. We focused our implementation on clean architecture so the behavior of objects and characters in water looks and feels like a natural extension of Roblox’s physics. This included integrating buoyancy into our standard physics pipeline; we consider a body of water to be a physics object and apply buoyancy to floating objects via the contact (or collision) between them and the water. Collisions between water and floater, floater and floater, and floater and sunken objects are all simulated in a unified engine.

Our architecture also unifies all the forces — buoyancy, water viscosity (drag) force, water-flow force, gravity, contact forces and other external forces. The movement of a floating object is a net result of all these forces on a rigid body following Newtonian laws.

We also implemented water and buoyancy simulation with a high level of detail. For example, think about dropping a cube into water. After gravity has submerged it in water, it’s likely going to tumble and re-orient itself as the water’s buoyancy forces it back to the surface. In Roblox, we simulate that re-orientation by dividing the cube into eight voxels, each of which has its own buoyancy interpolator.

By voxelizing the force of buoyancy on floating objects (cubes, wedges and corner wedges), they orient themselves properly when stabilized and respond accurately to uneven external forces, such as the pressure caused by a player standing on one corner. We also apply water viscosity force against both linear and rotational velocity to dampen the motion and add realism.

Another example: Our advanced water physics make a fine distinction between cross-section area and tangent surface area when we calculate water viscosity force on floating objects. In this demo video, we don’t apply any cheating forces or velocities to the boat body. Our engine simulates the actual interaction between the motorized paddles and the water surface to propel the boat. You can see that the thin boat travels faster than thick boat, even though both of them have the same submerged volume. The boats interact with other objects in the water, an example of our unified simulation of advanced water physics and rigid-body dynamics.

In Roblox, the final orientation of a voxel cube is affected by its density, as it would be in the real world.

Our water and buoyancy simulation facilitate a wide variety of practical applications, from boat modeling to real, water-fueled propellers. We’ve successfully created these, but believe our users will find ways to improve our primitive designs.

Future Evolution

Roblox is built on a comprehensive, realistic physics engine. It’s a fundamental part of our platform, bringing versatility and intuitiveness to the gameplay and game-creation experiences. While water and buoyancy physics represent a significant advance, facilitated by the efficiency of Assemblies and distributed physics, our vision is to continue optimizing Roblox’s physics engine so it can handle interactions between millions of parts and hundreds of players.

With such advanced physics simulation, Roblox users will be able to build anything they want in a massively multiplayer, online world, where dreams and reality converge.

Until then, the evolution continues.(source:gamasutra)


上一篇:

下一篇: