UE4物理系统浅析

版权声明:本文为原创文章,转载请保留原文链接。 https://blog.csdn.net/zzx023/article/details/82871707

1、概述

UE4(4.16)采用的物理系统为PhysX,版本为3.4。引擎层仅做接口的调用。物理以及渲染决定了一个游戏的美术表现。

 

2、碰撞体

UE4的碰撞体分为复杂碰撞和简单碰撞。碰撞体本身的作用就是为了提高碰撞的检测速度,用相对简单的包围盒把原物体包围起来,进行碰撞检测。

UE4物理系统浅析_第1张图片UE4物理系统浅析_第2张图片

如果使用复杂碰撞,也就是直接使用场景中物件的顶点以及三角面作为碰撞体的话,在进行碰撞检测时是非常复杂的。因此使用简单碰撞来代替复杂碰撞是非常有必要的。

    2.1 碰撞检测算法中的图元

从原理上可以区分为三类:

   1. 轴对齐包围盒(Axis-Aligned Bounding Box , AABB)

   2. 有向包围盒(Oriented Bounding Box , OBB)

   3. 离散有向包围盒(Discrete Oriented Polytope , k-DOP)

 

UE4物理系统浅析_第3张图片

它的长宽高三个轴与游戏内的是一致的,运算速度最快,但缺点是包围的不严密

UE4物理系统浅析_第4张图片

它的XYZ轴向是可以自定义的,可以相对精确的包围,运算速度快

UE4物理系统浅析_第5张图片

k-DOP可以最精确的包围,但运算速度最慢

   2.2 与PhyX的交互

PhysX中对象的基本单位与UE4中的数据交互通过结构体FBodyInatance来完成,包括顶点数据,位置,物理材质等等。

UE4物理系统浅析_第6张图片

例如我们要改变一个Actor的位置,我们是在UE4中设置Actor的Location去完成的。实际上是通过了UPrimitiveComponent中的FBodyInstance把位置赋到PxRigidBody中Shape上的Mesh去实现的。

 

3、碰撞检测

碰撞检测是游戏逻辑的重要组成部分,移动,自动瞄准,逻辑出发等等。

    3.1 碰撞检测的分类

我们游戏中主要用到的碰撞检测(Query Only)分为三类:

    1. Raycast(零大小的射线检测,即有向线段碰撞检测)

SingleLineTrace

    2. Sweeps(非零大小的检测,即扫描体积)

SingleSphereTrace,SingleBoxTrace

   3. Overlaps(空间体积相交检测)

 

 

Raycast:

UE4物理系统浅析_第7张图片

 

Sweeps:

UE4物理系统浅析_第8张图片

Overlaps:

UE4物理系统浅析_第9张图片

 

   3.1.1 Charactor的移动

UE4中Charactor的移动并不是物理模拟的,也就是说Charactor并不会受实际的重力,摩擦力以及其他的一些力影响的,而是在逻辑层中首先对Charactor在当前的速度方向上进行一个很短的距离移动,然后通过Sweeps对这个Charactor与场景以及其他物体进行一个自上而下的碰撞检测,得到碰撞的位置,最后通过一个接口,强行把Charactor挪到这个位置去。

实际上并不是通过PhysX的物理模拟去完成的。

大家有空可以思考一下,为什么会这样设计,挺有意思的。

 

   3.1.2 主动相交检测与内置相交检测

主动相交检测:

UE4物理系统浅析_第10张图片

UE4物理系统浅析_第11张图片

例如,如果需要实现类似手雷爆炸造成伤害这类需求,就可使用主动相交检测

 

内置相交检测:

UE4物理系统浅析_第12张图片

UE4物理系统浅析_第13张图片

例如,如果需要实现类似陷阱的需求,就可使用内置相交检测

 

每次发生位置改变时都会更新Overlaps的信息

Generate Overlap Events勾选开关后,可以监听消息,分为开始相交和结束相交

需要注意的是,这个overlaps的操作是在移动后增加的,会有一些额外的损耗

 

最后主动相交检测与内置相交检测的区别以及注意点在于:

    1.Overlaps接口为主动测试

    2.bGenerateOverlapEvent标记为调用Sweeps接口后,UE4底层代码主动执行Overlap接口

    3.因为每个骨骼都有一个碰撞盒,所以需要尽量避免开启SkinMesh碰撞体的bGenerateOverlapEvent。

 

    3.2 物理通道

UE4物理系统浅析_第14张图片

首先要说明以点,PhysX中并没有物理通道这个东西。

上图就是在UE4中,我们经常接触的碰撞通道。

在物理检测中,碰撞通道实际上是PxFilterData中的一组掩码。物理查询通过PxSceneQueryFilterCallBack的继承,也就是说PhysX他提供了一个Query接口给用户去自定义自己的逻辑,重写preFilter与posFilter实现了逻辑层的通道逻辑。在UE4中,如果他发现两者掩码的与值为1,这时在preFilter中返回一个Ignore的结果,就说明这个物件不是检测所需要的物件。

所以当我们在物理通道上如果碰到一些瓶颈时,我们就可以通过重写preFilter与posFilter去实现一些比较特殊的功能,比如说在UE4中的碰撞检测中有个IngoreActor的功能,他就是通过存储一个Actor的唯一ID,然后preFilter中去判断检测物体的唯一ID是否和存储的ID是否相同,最后去通过是否需要Ignore。

 

在物理模拟中,通过增加FPhysSceneShaderInfo的filterShader,实现了物理模拟中的逻辑层的通道逻辑。

 

4. 物理模拟

物理模拟通过设置SimulatePhysics来开启或关闭。

一旦开启物理模拟,也就意味着这个物体的所有运动状态都交由PhysX物理世界全权控制,它会受到相关的很多力的影响,例如重力,摩擦力,空气阻力等等。

在UE4中,逻辑层不提供直接的接口来直接控制物理状态,但可以通过UE4提供的一些接口强行设置一些物理状态,例如速度。

UE4物理系统浅析_第15张图片

但是需要注意的是,这样强行设置之后,Actor的物理就会变得非常奇怪,会有一些意想不到的表现。

所以如果我们使用了物理模拟,我们需要做的,就是把Actor的所有运动状态交给物理引擎去模拟,而尽量不要自己人为的去控制。(比如一些流体的模拟,以及物体破碎,汽车等载具的模拟)

    4.1 SimulatePhyscis的一些参数

UE4物理系统浅析_第16张图片

   1. PxRigidDynamicFlag::eKINEMATIC标记:设置为Ture时表示物体作为可以移动、不受外力的物体,否则可以受到重力等其他外力的影响。

    2.  Damping:阻尼,阻尼运动状态变化的参数,仅当eKINEMATIC为false的时候,即SimulatePhyscis时候生效

    3.  Constrains:物理行为约束,影响物理模拟的结果

 

需要注意的是,不管有没有勾选SimulatePhyscis,物体其实都是存在于PhysScene中的。

有一种错误的理解是如果没有勾选SimulatePhyscis,那么Actor是不和PhysX交互的,这是一个错误的理解,而对于PhysX来说,SimulatePhyscis可以理解为只是在PhysX层的一个标记而已,表示这个物体的物理状态是由逻辑层全权控制还是由物理层全权控制。

 

Physics下面的所有属性设置,都是在勾选了SimulatePhyscis的前提下,才生效的。

    4.2 SimulatePhysics的一些接口

UE4物理系统浅析_第17张图片

 

    1. 这些接口需要在开启SimulatePhysics的Component上面调用。

    2. Force的效果是持续的,有一定的过程,需要在Tick里面调用。

    3. Impulse的效果是瞬时的,直接改变物体的速度。

    4. Force是通过改变物体的加速度从而改变物体的运动状态的,有一定的延迟。

    4.3 物理材质

物理材质是描述当前物理体与物理世界交互的相关物理属性,它本质是一组参数,并不是和渲染相关的材质。

物理材质通过UE4逻辑层传递给PhysX来描述物理的一些特质,例如摩擦力,弹力,膨胀系数等等。

实际应用当中,主要用于根据物理材质的表面类型不同,去定制化的表现一些特效以及音效;以及为物理模拟提供参数。

需要注意的是在UE4中不存在物理材质为NULL的情况,在编辑器里如果不赋值物理材质,则实际存在一个默认的物理材质,不存在没有物理材质的情况。

5.碰撞检测与物理模拟的区别

碰撞检测:

    1.主动或者被动的对场景进行相关的碰撞检测,返回查询的结果

    2.通过逻辑层调用PhysX的接口raycast,sweep和overlap实现

物理模拟:

1.把物体的运动状态交由物理系统来全权管理

2.不需要任何的接口调用,通过PxScene::simulate对场景进行模拟

区别:

    1.碰撞检测是静态的,查询场景中满足给定Filter的Shape,处理eSCENE_QUERY_SHAP标记(Query Only)的Shape。像上面介绍的Charactor的移动,并没有开启物理模拟,而是通过碰撞检测去实现的。

    2.物理模拟是动态的,处理eSIMULATION_SHAPE标记的Shape。

    3.碰撞的可控性比较强,而对于物理模拟,如果要改变他的运动状态,那么只能通过添加力或冲量,或者是改变物理参数来改变模拟的结果。

    4.虽然不管碰撞检测还是物理模拟在UE4中看起来都是使用一样的物理通道,但实际的底层实现是不一样的,在物理层当中,这两个是完全没有任何关系的。

    5.碰撞检测是UE4与PhysX的PxScene进行交互,而物理模拟是UE4通过FBodyInstance与PhysX的PxRigidBody交互。

 

 

最后,是一张UE4物理系统大致的框架图:

 

UE4物理系统浅析_第18张图片

 

如有不对的地方,欢迎各位大佬留言修正!

感谢

你可能感兴趣的:(UE4)