最简单的 UE 4 C++ 教程 —— 注册组件的 Hit 事件【十五】

1,354 阅读2分钟

原教程是基于 UE 4.18,我是基于 UE 4.25

英文原地址

核心 API

SetSimulatePhysics

SetNotifyRigidBodyCollision

BodyInstance.SetCollisionProfileName

OnComponentHit.AddDynamic

接上一节教程,在本教程中,我们将学习如何在组件上注册一个 hit 事件。创建一个新的 C++ Actor 子类并将其命名为 OnComponentHit 。在头文件中,将声明一个 UBoxComponent 变量和一个当组件注册一个 Hit 事件时运行的 void 函数。

下面是最终的头文件

OnHitComponent.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "OnComponentHit.generated.h"

UCLASS()
class UNREALCPP_API AOnComponentHit : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	AOnComponentHit();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	UPROPERTY(VisibleAnywhere)
	class UBoxComponent* MyComp;

	UFUNCTION()
	void OnCompHit(UPrimitiveComponent *HitComp,
                         AActor *OtherActor, 
                         UPrimitiveComponent *OtherComp, 
                         FVector NormalImpulse, 
                         const FHitResult &Hit);
	
};

在 .cpp 文件中,首先 #include BoxComponent.h 头文件 。

#include "OnComponentHit.h"
// include files
#include "Components/BoxComponent.h"

接下来,我们将在 actor 的构造函数中为 actor 设置默认值。我们将用 UBoxComponent 初始化 actor ,并将其设置为 RootComponent 。然后,我们将添加 OnComponentHit 到组件,并将它连接到我们的 OnCompHit 函数。我们将在下一步创建 OnCompHit (回调函数) 。我还将默认的 CollisionProfileName 设置为 BlockAllDynamic ,这可以稍后在编辑器中更改。

// Sets default values
AOnComponentHit::AOnComponentHit()
{
    // 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;

    // Use a sphere as a simple collision representation
    MyComp = CreateDefaultSubobject<UBoxComponent>(TEXT("BoxComp"));
    MyComp->SetSimulatePhysics(true);
    MyComp->SetNotifyRigidBodyCollision(true);

    MyComp->BodyInstance.SetCollisionProfileName("BlockAllDynamic");
    MyComp->OnComponentHit.AddDynamic(this, &AOnComponentHit::OnCompHit);

    // Set as root component
    RootComponent = MyComp;
}

现在让我们创建简单的 OnCompHit 函数,当我们的 actor 撞击它时,它将打印并显示其他 actor 的名字到屏幕上。关于 OnComponentHit 的更多信息,你可以在访问一些不错的 AnswerHub 帖子1帖子2,或者在这里访问 ue4 文档

void AOnComponentHit::OnCompHit(UPrimitiveComponent *HitComp, AActor *OtherActor, UPrimitiveComponent *OtherComp, FVector NormalImpulse, const FHitResult &Hit)
{
    if ((OtherActor != NULL) && (OtherActor != this) && (OtherComp != NULL))
    {
        if (GEngine)
            GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, FString::Printf(TEXT("I Hit: %s"), *OtherActor->GetName()));
    }
}

以下就是最终完整的 .cpp 文件

#include "OnComponentHit.h"
#include "Components/BoxComponent.h"

// Sets default values
AOnComponentHit::AOnComponentHit()
{
 	// 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;

	// Use a sphere as a simple collision representation
	MyComp = CreateDefaultSubobject<UBoxComponent>(TEXT("BoxComp"));
	MyComp->SetSimulatePhysics(true);
	MyComp->SetNotifyRigidBodyCollision(true);
	MyComp->BodyInstance.SetCollisionProfileName("BlockAllDynamic");
	MyComp->OnComponentHit.AddDynamic(this, &AOnComponentHit::OnCompHit);

	// Set as root component
	RootComponent = MyComp;

}

// Called when the game starts or when spawned
void AOnComponentHit::BeginPlay()
{
	Super::BeginPlay();
}

// Called every frame
void AOnComponentHit::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
}

void AOnComponentHit::OnCompHit(UPrimitiveComponent *HitComp, AActor *OtherActor, UPrimitiveComponent *OtherComp, FVector NormalImpulse, const FHitResult &Hit)
{
    if ((OtherActor != NULL) && (OtherActor != this) && (OtherComp != NULL))
    {
        if (GEngine)
            GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, FString::Printf(TEXT("I Hit: %s"), *OtherActor->GetName()));
    }
}

编译代码。将 actor 拖放到游戏场景中。添加一个静态网格到该 actor,并调整尺寸以适应 Hit 框。当你按下 play 时,actor 应该注册 Hit 事件。

运行的结果