在上一篇中,我们设置了火球术从发射到击中敌人的整个周期使用的音效和特效,现在看上去它像一个真正的火球术了。在这一篇文章里面,我们主要解决一下火球术碰撞的问题,现在已知的问题是,有些不需要和火球产生碰撞的物体(比如药瓶)需要修复,有些场景静态物体无法和火球产生碰撞(比如立柱)都是我们需要解决的。
碰撞预设
碰撞主要分为四个部分:
- 碰撞预设:UE内置的碰撞设置,可以一键修改对应的内容。
- 设置碰撞:可以根据物理设置碰撞开关,只查询还是会产生碰撞
- 对象类型:相当于我们定义的当前物体的类型,对物体进行了分类,方便我们设置物体对不同的类型相应修改。
UE内置了很多的预设,它会将其它三项的修改保存为一个配置项一键切换的快捷键。
设置碰撞可以根据需求进行设置。
对象类型这里,为UE内置的几种,给我们分好的类型,场景内的静态(建筑)和动态物体(药瓶),角色Pawn,模拟物理的类型等等,后面我们也会创建自己的类型。
这里主要分为了两大块,一块是碰撞响应,另一块是对象于其它类型之间的响应。我们可以在项目设置里面增加对应的通道。
碰撞检测通道主要是用于鼠标拾取时,需要设置对应通道,比如,物体设置Visibility重叠,也就意味着将物体添加到了Visibility响应列表,在射线拾取时,可以节省计算性能。
物体相应则是物体之间的响应,而且必须要双方都设置成阻挡或重叠才可以实现,单方面无法实现响应。
重叠指两个物体重叠时,并且设置重叠相应,生成重叠事件为true时能够获取到重叠事件回调
阻挡相当于是物体产生碰撞时,将会阻挡住物体继续前进。
创建新的碰撞类型
这里我们实现自定义一个新的碰撞类型,作为火球术使用的类型。
我们找到引擎-碰撞,这里可以添加新的碰撞类型,新的检测通道,以及设置新的预设。
我们添加一个新的碰撞类型,设置为Projectile
然后你在重新打开物体的碰撞,会发现,物体增加了对应的类型和碰撞设置
如果在代码中使用,我们需要先定义,这样方便后面修改,在代码文件夹根目录找到项目的.h文件,这样方便其它文件引用,ECollisionChannel::ECC_GameTraceChannel1代表我们添加的碰撞类型的第一个类型,我们将其定义为自己需要名称。如果列表修改了,我们也只需要修改后面的数字即可。不会去代码里面修改每个名称数字。
cpp
#define ECC_PROJECTILE ECollisionChannel::ECC_GameTraceChannel1
有了自定义类型,我们在蓝图中,可以在配置项直接修改它的类型,在代码中将需要使用代码修改
我们在火球的基类发射物类的构造函数这里,创建了碰撞体以后,使用代码设置一下它的碰撞类型即可。
cpp
AProjectile::AProjectile()
{
...
//初始化碰撞体
Sphere = CreateDefaultSubobject<USphereComponent>("Sphere");
SetRootComponent(Sphere); //设置其为根节点,
Sphere->SetCollisionObjectType(ECC_PROJECTILE); //设置发射物的碰撞类型
...
设置于自定义碰撞类型的重叠事件
如果你在蓝图中设置实现,需要在碰撞体这里开启生成重叠事件,并且将对应项设置为重叠,即可实现事件。
如果你在代码中设置,那么需要调用对应的函数
比如,我在角色上面,设置了,不会响应相机碰撞,但是对发射物类型产生重叠事件,并开启了重叠事件。
cpp
GetCapsuleComponent()->SetCollisionResponseToChannel(ECC_Camera, ECR_Ignore);
GetCapsuleComponent()->SetCollisionResponseToChannel(ECC_PROJECTILE, ECR_Overlap); //设置碰撞体可以和发射物产生重叠
GetCapsuleComponent()->SetGenerateOverlapEvents(true); //设置碰撞体可以生成重叠事件
设置发射物身上的碰撞
在发射物身上,同样需要开启重叠事件,并且要设置查询,将类型设置为我们自定义类型。
在代码中设置就是如下
cpp
//初始化碰撞体
Sphere = CreateDefaultSubobject<USphereComponent>("Sphere");
SetRootComponent(Sphere); //设置其为根节点,
Sphere->SetCollisionObjectType(ECC_PROJECTILE); //设置发射物的碰撞类型
Sphere->SetCollisionEnabled(ECollisionEnabled::QueryOnly); //设置其只用作查询使用
Sphere->SetCollisionResponseToChannels(ECR_Ignore); //设置其忽略所有碰撞检测
Sphere->SetCollisionResponseToChannel(ECC_WorldDynamic, ECR_Overlap); //设置其与世界动态物体产生重叠事件
Sphere->SetCollisionResponseToChannel(ECC_WorldStatic, ECR_Overlap); //设置其与世界静态物体产生重叠事件
Sphere->SetCollisionResponseToChannel(ECC_Pawn, ECR_Overlap); //设置其与Pawn类型物体产生重叠事件