使用 OnComponentHit UE4 C++ 进行碰撞检测

Kam*_*len 2 c++ unreal-engine4

我遇到碰撞问题。我想做简单的射弹。我制作了一个具有根、球体和网格组件的 Actor。当这个演员击中目标物体时,什么也没有发生。我已经尝试了很多方法,也与

void OnOverlapBegin(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);


void OnOverlapEnd(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);
Run Code Online (Sandbox Code Playgroud)

功能,但没有任何结果..

这是我的自定义射弹的构造函数:

AProjectile_2::AProjectile_2()
{
    // 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;

    Root = CreateDefaultSubobject<USceneComponent>(TEXT("Root"));
    RootComponent = Root;

    mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("staticMesh"));
    static ConstructorHelpers::FObjectFinder<UStaticMesh>SphereMeshAsset(TEXT("/Game/StarterContent/Shapes/Shape_Sphere.Shape_Sphere"));
    if (SphereMeshAsset.Succeeded())
    {
        mesh->SetStaticMesh(SphereMeshAsset.Object);
        mesh->SetWorldScale3D(FVector(0.2f));
    }
    mesh->SetEnableGravity(true);
    mesh->SetSimulatePhysics(true);
    mesh->SetupAttachment(Root);

    Sphere = CreateDefaultSubobject<USphereComponent>(TEXT("SphereComponent"));
    Sphere->InitSphereRadius(5.f);
    Sphere->SetupAttachment(Root);

    Sphere->SetCollisionProfileName(TEXT("Target"));

    Sphere->OnComponentHit.AddDynamic(this, &AProjectile_2::OnHit);
    Sphere->SetupAttachment(RootComponent);

    InitialLifeSpan = 5.f;
}
Run Code Online (Sandbox Code Playgroud)

这是一个检测函数

void AProjectile_2::OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit)
{
    if ((OtherActor != NULL) && (OtherActor != this) && (OtherComp != NULL))
    {
        if (OtherActor && (OtherActor != this) && OtherComp && OtherActor->GetClass()->IsChildOf(ADestroypack::StaticClass()))
        {
            destroypack = (ADestroypack*)OtherActor;
            destroypack->decreasehp(50);
            destroypack->check_hp();
            destroypack->showhp();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我的网格物体开始移动

void AProjectile_2::Initvel(FVector Velocity)
{
    mesh->AddForce(Velocity * 300);
}
Run Code Online (Sandbox Code Playgroud)

这是我用人民币按钮拍摄的角色功能

void AHero::Attack_right()
{
    FVector Location = GetWorld()->GetFirstPlayerController()->GetPawn()->GetActorLocation();
    FRotator Rotation = GetWorld()->GetFirstPlayerController()->GetPawn()->GetActorRotation();

    GetActorEyesViewPoint(Location, Rotation);
    projectiles = (AProjectile_2*) GetWorld()->SpawnActor(AProjectile_2::StaticClass(), &Location, &Rotation);
    FVector LaunchDir;
    LaunchDir = GetActorForwardVector() * 5000.f;
    projectiles->Initvel(LaunchDir);
}
Run Code Online (Sandbox Code Playgroud)

如果有人能说出我做错了什么,或者我的项目中缺少什么,我将不胜感激。

好的!我已经弄清楚了!:D 我在将重力和物理添加到网格和球体时犯了一个错误。我已经从网格中删除了它,现在它可以工作了:)

AProjectile_2::AProjectile_2()
{
    // 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;

    //Root = CreateDefaultSubobject<USceneComponent>(TEXT("Root"));
    //RootComponent = Root;

    Sphere = CreateDefaultSubobject<USphereComponent>(TEXT("SphereComponent"));
    Sphere->SetSimulatePhysics(true);
    Sphere->SetEnableGravity(true);
    Sphere->SetNotifyRigidBodyCollision(true);
    Sphere->InitSphereRadius(40.f);
    Sphere->BodyInstance.SetCollisionProfileName("BlockAllDynamic");
    Sphere->SetCollisionProfileName(TEXT("Target"));
    Sphere->OnComponentHit.AddDynamic(this, &AProjectile_2::OnHit);
    RootComponent = Sphere;

    mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("staticMesh"));
    static ConstructorHelpers::FObjectFinder<UStaticMesh>SphereMeshAsset(TEXT("/Game/StarterContent/Shapes/Shape_Sphere.Shape_Sphere"));
    if (SphereMeshAsset.Succeeded())
    {
        mesh->SetStaticMesh(SphereMeshAsset.Object);
        mesh->AddRelativeLocation(FVector(0.f, 0.f, 0.f));
        mesh->SetWorldScale3D(FVector(0.2f));
    }
    /*mesh->SetEnableGravity(true);
    mesh->SetSimulatePhysics(true);
    mesh->SetGenerateOverlapEvents(true);*/
    mesh->SetupAttachment(RootComponent);

    InitialLifeSpan = 5.f;
}
Run Code Online (Sandbox Code Playgroud)

Chr*_*ong 5

您应该在函数中添加动态委托BeginPlay。与球体组件设置相关的其余代码可以保留在构造函数中。原因是在 Unreal 中,如果您首先制作了蓝图,将其作为射弹 cpp 类的父级,但随后添加了OnComponentHit构造函数中声明的功能,则它将无法工作。OnComponentHit如果蓝图从一开始就是使用 cpp 类(包括委托)制作的,那么它只能在构造函数中工作。这是一个非常常见的问题,但常常被忽视。

BeginPlay如果您还没有这样做,请确保将该函数添加到您的头文件中,

virtual void BeginPlay() override;
Run Code Online (Sandbox Code Playgroud)

然后在您的 cpp 文件中,声明该函数并将您的调用AddDynamic从构造函数移至BeginPlay

void AProjectile_2::BeginPlay()
{
    Super::BeginPlay();
    Sphere->OnComponentHit.AddDynamic(this, &AProjectile_2::OnHit);
}
Run Code Online (Sandbox Code Playgroud)