ue4蓝图碰撞检测的类型_UE4 C++ —— 碰撞检测

简述

UE4集成了PhysX物理引擎,用来模拟刚体的物理行为,包括常用的碰撞响应。

碰撞基础概念

碰撞对象通道

每个碰撞体都会设置一种(Object Responses)碰撞对象通道,碰撞对象通道可以是ue4默认的几种,也可以新建自定义的碰撞对象通道

新建自定义的碰撞对象通道,点击Project Settings->Collision

在Collision窗口里,找到Object Channelse项,点击New Object Channelse新建碰撞类型,设置名称和默认响应类型,这里新建两个碰撞对象类型Cube, Sphere

碰撞响应设置

类型

详解

NoCollision

无碰撞响应

Query Only(No Physics Collision)

只会触发Overlap(重叠)事件,无刚体碰撞响应

Physics Only(No Query Collision)

只有刚体碰撞响应,不触发Overlap(重叠)事件

Collision Enabled(Query and Physics )

刚体碰撞响应和Overlap(重叠)事件都可以

碰撞响应类型

两个物体发生碰撞时会产生不同的碰撞响应,

Block(碰撞),发生Block碰撞响应后,两个Actor之间会发生阻挡行为,并触发Hit事件

UFUNCTION()

void OnHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComponent, FVector NormalImpulse, const FHitResult& Hit);

Overlap(重叠) ,发生Overlap碰撞响应后,会触发Generate Overlap Events事件

UFUNCTION()

virtual void OnOverlayEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);

UFUNCTION()

virtual void OnOverlayEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);

Ignore(忽略),两个Actor忽略碰撞响应

碰撞响应

触发Block条件

(1)两个物体的碰撞响应都设置为Block

(2)其中一个物体必须设为Physics(刚体),勾选Simulate Physics项。

(3)要触发Hit事件,需开启Simulate Generates Hit Events.

触发Overlap条件

(1)其中一个物体的碰撞响应为Overlap,任何一个物体的碰撞响应都不能设为Ignore

(2)要触发重叠事件,需开启Generate Overlap Events

Ignore条件

(1)其中一个物体的碰撞响应为Ignore

碰撞实例应用

新建C++工程,创建两个Actor,命名为CubeActor和AphereActor,这两个物体将进行碰撞响应

现在这两个Actor是空的,我们需要在C++中给他们添加StaticMesh,并进行事件绑定

源码

CubeActor.h

#include "CoreMinimal.h"

#include "GameFramework/Actor.h"

#include "CubeActor.generated.h"

UCLASS()

class PROJECTDEMO1_API ACubeActor : public AActor

{

GENERATED_BODY()

public:

// Sets default values for this actor's properties

ACubeActor();

UFUNCTION()

virtual void OnOverlayBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult);

UFUNCTION()

virtual void OnOverlayEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);

UFUNCTION()

void OnHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComponent, FVector NormalImpulse, const FHitResult& Hit);

protected:

//根组件

class USceneComponent* RootScene;

//静态模型

UPROPERTY(EditAnywhere)

class UStaticMeshComponent* StaticMesh;

};

CubeActor.cpp

#include "CubeActor.h"

// Sets default values

ACubeActor::ACubeActor()

{

// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.

PrimaryActorTick.bCanEverTick = true;

//实例化根组件

RootScene = CreateDefaultSubobject(TEXT("RootScene"));

RootComponent = RootScene;

//创建静态模型组件

StaticMesh = CreateDefaultSubobject(TEXT("BaseMesh"));

StaticMesh->SetupAttachment(RootComponent);

StaticMesh->SetCollisionProfileName(FName("CubeProfile"));

//绑定检测方法到碰撞体

FScriptDelegate OverlayBegin;

OverlayBegin.BindUFunction(this, "OnOverlayBegin");

StaticMesh->OnComponentBeginOverlap.Add(OverlayBegin);

FScriptDelegate OverlayEnd;

OverlayEnd.BindUFunction(this, "OnOverlayEnd");

StaticMesh->OnComponentEndOverlap.Add(OverlayEnd);

FScriptDelegate DelegateHit;

DelegateHit.BindUFunction(this, "OnHit");

StaticMesh->OnComponentHit.Add(DelegateHit);

}

void ACubeActor::OnOverlayBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult)

{

if (GEngine) {

GEngine->AddOnScreenDebugMessage(-1, 20, FColor::Yellow, "Cube Begin---------");

}

}

void ACubeActor::OnOverlayEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)

{

if (GEngine) {

GEngine->AddOnScreenDebugMessage(-1, 20, FColor::Yellow, "Cube End---------");

}

}

void ACubeActor::OnHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComponent, FVector NormalImpulse, const FHitResult& Hit)

{

if (GEngine) {

GEngine->AddOnScreenDebugMessage(-1, 20, FColor::Yellow, "ACubeActor OnHit---------");

}

}

注:在头文件中我们定义了三个函数,(OnOverlayBegin, OnOverlayEnd, OnHit)分别绑定Overlay进入事件,Overlay离开事件和刚体碰撞事件,这三个函数在事件触发后将打印语句到屏幕,接着定义了一个根组件和StaticMesh,在构造函数中创建组件和进行事件绑定,另一个AphereActor类的代码同上。

C++代码写完后,编译保存,打开编辑器,创建两个蓝图类,分别继承于CubeActor和SphereActor,命名为BP_CubeActor和BP_SphereActor。并添加三维模型。

Overlap(重叠)事件

我们想让BP_CubeActor和BP_SphereActor触发Overlap(重叠)事件,需要将BP_CubeActor和BP_SphereActor的碰撞对象通道分别设为Cube和Sphere,并把互相的碰撞响应设为Overlap

打开BP_CubeActor蓝图类,设置它的碰撞属性

勾选Generate Overlap Events,Collision Presets设置为customize(自定义),Collision Enabled设置为Query Only(No Physics Collision),Object Type设为Cube(前面自定义的碰撞对象通道),Sphere响应方式勾选为Overlap。

打开BP_SphereActor蓝图类,设置它的碰撞属性,设置方法相似。不同的是需要把Object Type设为Sphere,Cube响应方式勾选为Overlap。

碰撞属性配置完成后,实例化这两个Actor,将他们拖入Level中

打开关卡蓝图,让Sphere向Cube移动,触发Overlap(重叠)事件

编译运行,不断按下‘1’键,直到Sphere刚接触到Cube时,就会触发Overlap Begin事件,随之调用绑定到该事件的函数,打印语句到屏幕。同理,当Sphere离开Cube时,触发Overlap End事件。

Block(碰撞)事件

接下来我们要让BP_CubeActor和BP_SphereActor触发Block(碰撞)事件

打开BP_CubeActor蓝图类,设置碰撞属性,将Collision Enabled设置为Physics Only(No Query Collision),Sphere响应方式勾选为Block。

同上,设置BP_SphereActor的碰撞属性

在两个Actor实例中启用Simulate Generates Hit Events事件,并设置为Physics(刚体)

将Sphere拖动到Cube上方

编译运行,程序开始后Sphere受重力下落,触发Block事件,调用绑定函数,打印语句到屏幕

碰撞预制文件

除了前面的自定义碰撞属性,还可以使用碰撞预制文件来设置碰撞属性

点击Project Settings->Collision,打开Collision窗口。在Preset部分,点击New

设置名称和碰撞属性

创建两个碰撞预制文件,SphereProfile和CubeProfile

在蓝图中指定碰撞预制文件

也可以在C++代码中指定

StaticMesh->SetCollisionProfileName(FName("CubeProfile"));


版权声明:本文为weixin_39969976原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。