Unity中简单的优化物理系统


这个篇文章的主要目标是给予你一个关于在Unity中简单的优化物理系统


我的游戏物理系统有什么错误吗?


怎么去处理游戏物理系统?


Unity 物理系统有什么缺陷吗?


Unity 是怎样处理物理系统的?


我在 Unity 物理系统上做了什么控制?


在我开始使用游戏物理系统之前我应该关心什么事情?


我应该在时候避免使用物理系统?


我看到了帧速率在下降,这是否是物理系统导致的?


当涉及到物理系统时,便会有以上这些问题,或许你会有更多像上面类似的问题。


是的,是的,我知道!我们全怪那个平果,它为什么要在那一天降临到牛顿的头上?为什么呢,上帝?


物理学也许不是每个人最爱的科目,但是物理学在游戏开发行业中真的是一个非常重要的角色。


想象一种情况,在紧要关头你最终决定提出做一个大事情。一个让人瞩目的,一个使用逼真的物理和图像的大游戏。


设计已经创建出来,架构已经完成,一切看上去似乎已经准备就绪。但是你最终坐了下来,开始在最棘手的部分上工作,“物理系统”!!


此时,似乎所以东西都崩溃了;你无意中看到了很低的FPS,奇怪的移动,碰撞器/触发器 出现了问题,高CPU使用率等等。


不恰当或者不正确的使用物理系统可能会把一些游戏玩家吓跑。这不只是关于不恰当的使用物理系统的问题了;这是关于一个游戏可玩性高不高的问题了。


这些都是不容易解决的问题。物理系统是游戏开发过程中最困难,也是最重要的一部份,这是无法避免的!!


人们可能会说:“好的物理系统需要一个超快的CPU!”。


但是,请相信我,这句话不一定都是对的。多数情况下,可以通过由浅入深进入Unity的海洋中学习Unity 的物理系统是怎样工作的,以便我们实现更好的物理系统。


在我还是一个程序小鲜肉的时候,我便要处理100多个与物理相关的事情。这让我花了近一年的时间记录下了处理物理相关的关键点。


因此,我决定写这篇文章。帮助大家跳跃这个学习阶段的痛苦,成为一个专业的物理系统开发者。


我不打算讲关于物理系统在Unity中是如何工作的,然而我将会在怎么优化你的物理系统中列出技巧和要点。所以,如果你是一个新手,我建议你先去大概了解一下Unity 物理系统。


物理学是一个非常非常庞大的、广泛的概念,我决定分成不同的部分,尽可能做到简单。


接下来,这是一个漫长有趣的过程,请你赶紧系好你的安全带,让我们开始吧!


降低固定时间步(Fixed Timestep)

在Unity文档的说明如下:


“一个不受帧速率影响的时间间隔,用于指定在 FixedUpdate() 函数中执行物理计算每一帧的时间间隔


默认值为 0.02(每秒),这显示了每 20ms(毫秒)物理更新将会被执行一次。所有 FixedUpdate() 也会每20ms调用一次。


你需要不停的改变这个值,以获得理想的效果。


例如:


“如果你打算做一个简单的卡牌游戏,这不需要使用太多的物理系统。然而最好减少调用物理引擎的次数。但是这操作要很细心一点;如果你减少过多的物理引擎调用的次数,你也许不会得到你想要的物理效果。”


让我们通过下面的案例更好的理解 Fixed Timestep 吧!


步骤 1) 创建 3-4 个 球体。让他们保持一些距离:




步骤 2)创建物理材质(通过在Assest文件夹中按下右键->Create->Phycics Material),并且设置摩擦系数(Friction Amount)的数值为 0 ,然后设置弹力系数(Bounciness)为 1,再设置弹力混合(Bounce combine)为最大值:




步骤 3)将该物理材质添加到球体碰撞器的物理材质卡槽中去:




步骤 4)为球体添加刚体组件(这将意味着此物体时物理对象):




步骤 5)创建一个平面,并且为其创建一个物理材质(先使用默认值),添加到平面上:




步骤 6)让创建的球体位于平面的上方,并且设置球体的重力选项盒为勾选状态。




步骤 7)点击 Play 按钮,并且查看一下结果。


这个球在做一下一上的动作。(不好意思,污了一下下。)


那么,这与固定时间步(Fixed Time Step)有什么关系呢?


上面只是一个简单的设置,现在我让我们开始玩耍 Fixed Time Step 的值吧!


找到 Edit>>Project Settings >> Time,在那里,你能找到 Fixed Time Step ,它的默认值为 0.02 (正如我之前提到的那样)。




现在让我们设置它为 0.1,然后按下 Play 按钮开始游戏。


你有发现有什么不同吗?


首先你会注意到,这些球的运动非常的慢。


然后,你会看到球体穿过了平面而不是反弹回来。


你会问为什么?(不需要弹跳如此的快呀!啊哈哈)


好的,如果你设置 Fixed Time Step 为 0.1,这就意味着物理更新将在每100ms(毫秒)执行一次,这很快就会注意到,将无法检测到碰撞。


这表明,过多的降低 Fixed Time Step 的也是不恰当的。现在让我们改变 Fixed Time Step

的值为一个更为实际可行的值 0.03 - 0.04。(具体根据球体的需要来定)


现在,如果你开始游戏,你不会看到任何改变。只要看上去还行,那就OK。如果你细心的检查一番,物理碰撞检测会有一点点不同的。


看看下面的图片:




提示

如果你不能跟上步骤来,那么请你参考一下Unity的官方文档。适当的理解 Unity 物理引擎是必须的。

物理碰撞检测会有点延迟,只会在当前帧结束之后才反弹回去。


这在你游戏处于正常FPS下可能观察不到,但是这可能会影响到物理效果。但只要你的需要满足了,这也是没什么关系的。


这将有什么帮助呢?


任何时候你从物理计算中节省下来的计算资源,都可以让给渲染和其他计算密集的处理,所以就可以让你的游戏更加出众。


通过设置 Maximum Allowed Timestep 在物理系统中保持检查!


在Unity文档中的定义如下:


“一个不受帧速率影响的时间间隔,当帧率为最低峰值的时候,物理计算和 FixedUpdate() 事件将不会被执行”


那么,这意味着什么呢?


让我们先在正常的游戏下,去理解它(Maximum Allowed Timestep)。


如果你的游戏在运行的时候能保持在 60 FPS,这就意味着每一帧会执行 0.01666秒。意味着每一帧需要花费 16.7ms(毫秒)。


现在,让我们把 Fixed TimeStep 设置为 0.01,这表明物理更新将每 10ms 执行一次。


这表明,在每一帧中至少会调用一次物理更新,因为 10ms<16.7ms. 现在让我们假设由于某种原因帧率降低到了 30 FPS。


那么,每一帧将会执行 0.0333秒(也就是33.3ms) 。也就意味着在每一帧中会调用3次物理更新(因为一次物理更新花费10ms)。这意味着如果帧率继续下降,每帧内的物理调用还会更多。


这将会导致程序崩溃。为了解决这个问题,下面引入 Maximum Allowed TimeStep。


它的默认值为 33ms(可能是作者搞错了,明明就是0.33333秒 = 333。33ms啊)。正如 Maximum Allowed TimeStep 定义:每当物理更新超过指定的时间,物理更新将会停止。因此,这便为其他进程节约了资源。


在我们的案例中,如果每一帧执行时间增加到 40ms,这将会调用更多的物理更新。


但是现在我们设置 Maximum Allowed TimeStep 为 0.033,也就是33ms ,物理更新将会在 33ms 后停止调用,也就是执行3次物理更新后,便会停止调用,尽管每帧的执行时间超过 50ms 也会如此。


因此为其他沉重的进程节省下一些资源。


这听起来非常的棒,不是吗?


但还是有会一些限制的负面影响。每当发生性能故障,动画和物理便会放慢(意味着画面卡顿,延迟)。


因此,要牢记Maximum Allowed TimeStep 同样是一个重要的因素,如果使用得当,将会得到非常好的效果。


总是有 1-1-1 的比例


放大一个没有物理的对象是没有问题的(就是没有与物理相关组件的物体对象),但是当一个物体时一个物理对象时,我建议你不要对该物体进行缩放。缩放会导致奇怪的碰撞检测,也会影响到物体的下落方式。


例如:


“一块大石头在没有任何空气阻力的情况下会很快的落到地面上(如从塔上或其他地方掉下来)。但是如果它周围的物体都放大了,那会让下落看起来速度很慢”。



还有一个选项是调整重力加速度的值让他看起来变得正常,但是这不是最正确的做法。正确的做法应该是保持使用1-1-1的缩放比例,因为Unity的物理引擎在这种情况下工作的最佳。


给你的对象设置恰当的质量


和缩放一样,质量也需要保持精确。


让一架飞机的质量为 1kg 正确吗?


如果你考虑到度量系统准则,Unity的 1 个单位等于 1 kg 质量。同样的,Unity的 物理系统是无量纲的。但是,如果你假定 Unity 的一个单位的长度为米,那么,一个质量的单位为 kg。


你可以得到更完美的结果。并且,Unity在努力解决高浮点数问题,所以尽量削减取值范围是比较理想的解决方案。


这意味着,如果假设你的飞机重 1kg ,那么你的轮子必然不会超过 1/1000 kg。


尽可能避免使用网格碰撞器(Mesh Collider)


对任何物理引擎来说,基于网格的碰撞检测都比原始的碰撞检测需要更多的计算量,这是一个事实。Unity在内部使用了 Nvidia 的 PhysX,因此这是没有什么不同的。


一般来说,


“对于不同碰撞检测的相对成本从高到低的排序为:三角形网格、凸包(具体可以百度百科)、胶囊体、球体、盒子(六面体)、平面、点”


通常,网格碰撞器(Mesh Collider)被标记为凸包(也建议大家这么标记),它将被限制到255个三角形。只有在两个网格碰撞器被标记为凸面(Covex)时才能相互发生碰撞检测。




在 Unity 文档中的说明:


”使用网格碰撞器时会有一些限制。没有标记为凸面(Convex)的网格碰撞器只支持在一个没有刚体组件的游戏对象(GameObjecet)上发生碰撞,如果你想要在一个刚体上使用一个网格碰撞器,这必须要标记为凸面“


理想情况下,应该尽量避免使用网格碰撞体,因为他们会比传统的碰撞器(球体,立方体,胶囊体)带来更多的计算负载,所以最好还是少用。


替代方案是什么呢?




一个简单的替代方法就是让对象的子物体使用原始(传统)碰撞器把它们组合起来(如上图所示)。这样会减少一定的计算量,因为原始(传统的)碰撞器计算速度比较快。


对于复杂的网格,你通常可以使用 Blender(小巧的建模软件)或者其他工具来将它们分解成一些小部分。然后可以用传统碰撞器直接替换掉这些小部分的网格。


我希望我已经给你一个确切的优化描述,但是不幸的是,每个网格都是不一样的,对于我给出一个确切的描述是非常困难的。


后续很快就会来到


这个列表会很长,而且看上去会没有尽头,所以让我们先休息一下,后续的博客会继续介绍其他的提示。


同时我也不希望你一下看太多关于物理的东西而产生不适。


请继续保持关注,然后先从上面几个点开始优化。如果你有更好的替代方案,请也和我们分享一下。如果对上面讨论的内容有任何问题,或者有任何疑问,请在评论区留言,我会很高兴能提供任何帮助。


总结:该篇文章大体讲了一下几个关键字:Fixed TimeStep、Maximum Allowed TimeStep、Mesh Collider、Convex。


这些东西都能在官网组件手册中找到一些详细的说明,如果看不懂该文章所说的内容,还请大家自行去看一看官网的组件手册(还记得我给你说的 Unity 圣典吗)



转载自公众号:Unity墙外的世界

  • 5
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值