UE4物理模块(三):碰撞查询

作者:Jerry 2019-04-02
前一文中介绍了如何在UE4中创建简单碰撞或者直接使用其mesh表示的复杂碰撞:

那么在拿到碰撞之后,就可以进行物理运算,主要是碰撞查询和物理仿真,这里先介绍更为常见的碰撞查询。

最为直观的碰撞查询就是人物的移动物理了,你所控制的人物不掉落地板之外或者碰到障碍物就被阻挡,这其实是碰撞查询在背后起作用,如下动图:


我们也可以让人物直接穿过盒子,如下:


人物的移动物理本身是一块非常多的内容,我在文末会给出一些不错的分析文章,在这里只要知道移动距离是根据初中物理所学s=v*t得到的,v是当前人物的移动速度,而t是移动时长,在游戏里面t是很小的时间片。游戏中并不会有真正的“连续”移动,当t足够小的时候,每次移动量也很小,将人物SetActorLocation到这个小移动量表示的世界坐标里,就可以得到看似连续的移动效果,本质是极小量的瞬移。

在每次计算移动位移时,都会进行碰撞查询,具体是用人物的胶囊体向速度方向进行扫略,它返回的结果是一个比例,如果比例是1.0,那么就可以执行完整的瞬移,而如果比例是0.5,就只能执行一半长度的瞬移,如果是0,就不进行任何移动。那么为何第一张动图被阻挡不能执行完整瞬移,第二张动图就偏偏可以呢?

这与“两方”的碰撞设置有关,碰撞是两个物件碰撞盒相交才会发生的事情,所以这里首先强调两方。碰撞响应总共有三个选项:Ignore,Overlap,Block。顾名思义,Ignore忽略碰撞,Block就是阻挡,而Overlap与Ignore类似,不会产生阻挡,但会产生重合的事件通知。两两组合就有下面的情况(图来自于https://www.unrealengine.com/zh-CN/blog/collision-filtering,也是一篇不错的碰撞查询入门文章):


其实只要记住两点:

(1)只有两个对象互相Block时,才会真正的被阻挡,其他情况都不会;

(2)只要有一方Ignore,就不会产生Overlap的重合事件;

在编辑器里,选中这个白盒子,在这里配置碰撞信息(Collison Preset,碰撞预设):


默认是Default,切换成其他的碰撞预设都能看到具体的碰撞响应,但大多都不可编辑(只读),如下图:


只有切成Custom...才可编辑:


我们来分别说下这些配置:

CollisionEnabled决定了碰撞的用途,如下:


NoCollision:如果是这个,那么其他碰撞设置都会被忽略不计,因为不再考虑碰撞了;

Query Only:仅用于查询,不会考虑物理仿真;

Physics Only:仅用于物理仿真,不考虑查询;

Collision Enabled(Query and Physics):同时用于查询与仿真;

人物的移动物理属于查询,我们选择Query Only就行。

ObjectType决定了物体本身是什么碰撞类型,可选类型如下(也可以在ProjectSettings里面添加,后面会谈到):


WorldStatic:静态几何物件,如山石,树干等;

WorldDynamic:动态几何物件,如房门,地面可拾取物等;

Pawn:人物或类人的东西,如玩家,野怪;

PhysicsBody:物理体;

Vehicle:载具,如摩托车,飞机等;

Destructible:可破坏物件,如栅栏,窗户等;

ObjectType配置的自由度很高,你也可以把石头配置成载具的ObjectType,只是这样在处理其他物件对它的响应时要绕得过来,一般不会做这种坑人坑己的事情。

碰撞响应决定了该对象对其他碰撞类型的响应,如下图:


仔细看可以发现碰撞响应还会细分成Trace Response与Object Response,个人理解其实差别不大,主要是通道过滤比较方便,直观理解射线检测类的配置成Trace Response,对象移动类的配置成Object Response就可以了。ObjectResponses列举出来的情况正是之前我们谈到的ObjectType的枚举,上图应解释成:白盒子对这几种碰撞类型的对象都是阻挡响应。

我们以第三人称人物为例,他本身碰撞类型是Pawn,如下:



注意我们看的是ObjectType,而不是上面的CollisionPresets。对人物而言,它对WorldStatic的响应是Block:


对于白盒子而言,它自身碰撞类型正是WorldStatic,而对Pawn的响应是Block,如下:


两两的碰撞响应都是Block,所以会发生阻挡。而如果将箱子对于人物的响应换成Ignore,如下:


则人物可以穿过箱子(大家试试看~)。

综上,每个物件的碰撞信息分成两块可配置:

其一,自身的碰撞类型ObjectType;

其二,这个物件对于其他碰撞类型对象的响应;

如果A的ObjectType是AO,B的ObjectType是BO,假定A配置成了Block BO,同时B配置成了Block AO,那么就会形成阻挡响应,彼此不能通过对方。

下面说下如何自定义碰撞类型,在菜单栏里面选择ProjectSettings,如下:


然后在左侧导航这里选择Engine->Collision,如下:


右侧可以新建自定义的ObjectChannels,TraceChannels以及Presets,前面提到过ObjectChannels与TraceChannels的区别主要在于通道的过滤,ObjectChannels还会创建一个同名的ObjectType。

对于ObjectChannels的碰撞响应过滤,我们使用蓝图中这个结点SingleSphereTraceForObjects(C++里面也有对应的函数),如下:


注意到ObjectTypes这里选择要过滤的通道,上图表示只有ObjectType为Pawn或者是PhysicsBody的对象才会被碰撞检测到,其他类型的对象则被忽略。

对于TraceChannels的碰撞,使用的是SingleSphereTraceByChannel这个结点,如下:


注意这里的通道过滤项是TraceChannel,上图表示只有配置成Block Weapon这个Channel的对象才会被检测到(体现在蓝图右侧OutHit输出结果上)。

此外,还有一些直观的理解,当你考虑的是对象移动时发生的碰撞,就用ObjectChannel(一开始UE的叫法是MovementChannels),如Pawn,StaticMesh;若考虑是射线检测时发生的碰撞,就用TraceChannel,如Weapon,Visibility。

举个例子,我们在ObjectChannel里面新加一个名为Pickup(表示地上的可拾取物)的碰撞Channel,如下:


将默认的碰撞响应配置成了Block,以使pickup默认会被其他碰撞类型阻挡(如果不想让人行走时被pickup拦下,可以在去修正某个Pickup对ObjectType为Pawn的响应。

在TraceChannel里面新加一个名为Weapon(表示枪的射线检测)的碰撞Channel,如下:


并将默认响应配置成了Block,即对默认对象类型来说枪射线会被阻挡。

回到编辑器场景窗口,并选中白盒子,查下其碰撞信息,如下:


可以看到TraceResponses和ObjectResponses这里已经多了之前添加的项目了。而且在ObjectType这里可以看到同名的ObjectResponses,如下:


还有一个Presets的自定义没说,回到Project setting这里:


所谓Presets就是碰撞预设,它是将一些常用的碰撞响应配置记录下来,这样以后新添一个对象时,就不用自己选择Custom,然后逐一勾选对不同ObjectType的响应了。比如这里我们配置一下Pickup的响应如下:


这样就可以看到PickupPreset最下面一行多了新加项(这里UE有一个UI上面的BUG,右侧的滚动条在第一次打开ProjectSetting是不会显示,也就无法向下滚动,这时只要再单击下Preset就可以了)。


这样我们就可以一键配置想要的碰撞信息了:


这里稍稍提到了LineTrace的蓝图配置,打算再分出一章详细说下蓝图里面的各种Trace,也是属于碰撞查询这个门类,就放到碰撞查询(下)里面说。

补一下UE移动这块非常好的文章:

《Exploring in UE4》移动组件详解[原理分析]
UE4的移动碰撞
UE4人物移动同步算法

作者:Jerry
专栏地址:https://zhuanlan.zhihu.com/p/60840943

最新评论
暂无评论
参与评论

商务合作 查看更多

编辑推荐 查看更多