如何在UE4 C++中使用OnActorBeginOverlap

问题描述 投票:0回答:1

我正在用 UE4 开发一个小游戏,遇到了一个小问题。

到目前为止,我已经让玩家在 C++ 中对敌人造成伤害(通过光线投射/线追踪)。现在我试图让敌人在他们的碰撞盒重叠时对玩家造成伤害。

玩家和敌人使用

TakeDamage()
功能互相造成伤害

目前,当两个碰撞重叠时,敌人确实会对使用此蓝图设置的玩家造成伤害。

我正在尝试将其翻译成 C++。 我一直在看许多网站,这些网站说要使用

OnActorBeginOverlap()
OnComponentBeginOverlap()
AddDynamic()
功能。但是,当尝试调用
OnActorBeginOverlap()
时,当我执行
BoxCollider->
OnComponentBeginOverlap()
时它不会出现,但没有
AddDynamic()
功能。据我了解,AddDynamic 是一个我不太熟悉的宏。
OnActorBeginOverlap()
确实出现没有
BoxCollider->
。两个对象都是演员。

有什么想法吗?

代码示例:

BasicZombie.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Components/BoxComponent.h"
#include "BasicZombie.generated.h"

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

    void Destroy();

    UPROPERTY(EditAnywhere)
        UBoxComponent* BoxCollider;

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

    virtual float TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, AActor* DamageCauser) override;



private:
    UPROPERTY(EditDefaultsOnly)
        float maxHealth = 100.0f;

    UPROPERTY(VisibleAnywhere)
        float health;

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

};

BasicZombie.cpp

#include "BasicZombie.h"
#include "MainCharacter.h"
#include "GameFramework/Actor.h"
#include "DrawDebugHelpers.h"
#include "Engine/Engine.h"

// Sets default values
ABasicZombie::ABasicZombie()
{
    // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = false;

    BoxCollider = CreateDefaultSubobject<UBoxComponent>(TEXT("BoxCollider"));
    BoxCollider->OnComponentBeginOverlap.AddDynamic(this, &AMainCharacter::OnCollision);

    health = maxHealth;


    
}

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

float ABasicZombie::TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, AActor* DamageCauser)
{
    float DamageToApply = Super::TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser);
    DamageToApply = FMath::Min(health, DamageToApply);
    health -= DamageToApply;
    UE_LOG(LogTemp, Warning, (TEXT("Health Remaining: %f")), health);
    //GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Red, FString::Printf(TEXT("Health Remaining: %f"), health));
    
    Destroy();

    return DamageToApply;
}

//void ABasicZombie::DealDamage()
//{
//  
//}



void ABasicZombie::Destroy()
{
    if (health <= 0)
    {
        UWorld* WorldRef = GetWorld();
        AMainCharacter* mainCharacter = Cast<AMainCharacter>(WorldRef->GetFirstPlayerController()->GetCharacter());
        mainCharacter->currentScore += 500;
        GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Green, FString::Printf(TEXT("Score: %i"), mainCharacter->currentScore));
        AActor::Destroy();
    }
}

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

MainCharacter.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"

#include "Camera/CameraComponent.h"
#include "Components/CapsuleComponent.h"
#include "Components/InputComponent.h"
#include "GameFramework/PlayerController.h"
#include "MainCharacter.generated.h"

class AHandgun;

UCLASS()
class MERCENARIES_API AMainCharacter : public ACharacter
{
    GENERATED_BODY()

public:
    // Sets default values for this character's properties
    AMainCharacter();

    void OnCollision(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComponent, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& Hit);

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

    virtual float TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, AActor* DamageCauser) override;

    

private:
    UPROPERTY(EditDefaultsOnly)
        TSubclassOf<AHandgun> HandgunClass;

    UPROPERTY()
        AHandgun* Handgun;

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

    // Called to bind functionality to input
    virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;

    //Handles Input for moving FORWARD and BACK
    UFUNCTION()
        void MoveForward(float value);

    //Handles input for moving RIGHT and LEFT
    UFUNCTION()
        void MoveRight(float value);

    UFUNCTION()
        void Shoot();

    UFUNCTION()
        void printHealth();

    //FPS camera
    UPROPERTY(VisibleAnywhere)
        UCameraComponent* MainCharacterCameraComponent;

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Gameplay)
        FVector MuzzleOffset;

    UPROPERTY()
        int32 playerScore;

    UPROPERTY()
        int32 currentScore;

    UPROPERTY()
        float maxHealth = 1000.0f;

    UPROPERTY(EditAnywhere, BlueprintReadWrite)
        float currentHealth;

};

MainCharacter.cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "MainCharacter.h"
#include "Engine/Engine.h"
#include "GameFramework/Actor.h"
#include "Handgun.h"
#include "GameFramework/Character.h"
#include "Components/SkeletalMeshComponent.h"


// Sets default values
AMainCharacter::AMainCharacter()
{
    // Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = true;

    //Create a first person camera component
    MainCharacterCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstPersonCamera"));
    check(MainCharacterCameraComponent != nullptr);

    //Attach the camera component to our capsule component
    MainCharacterCameraComponent->SetupAttachment(CastChecked<USceneComponent, UCapsuleComponent>(GetCapsuleComponent()));

    //Position the camera slightly above the eyes
    MainCharacterCameraComponent->SetRelativeLocation(FVector(0.0f, 0.0f, 50.0f + BaseEyeHeight));

    //Enable the pawn to control camera rotation
    MainCharacterCameraComponent->bUsePawnControlRotation = true;

    

    currentHealth = maxHealth;
    playerScore = currentScore;
}

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

    

    check(GEngine != nullptr);
    GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, TEXT("[MainCharacter DEBUG] - MainCharacter in use."));
    GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Green, FString::Printf(TEXT("[MainCharacter DEBUG] - Current Score: %f"), playerScore));

    Handgun = GetWorld()->SpawnActor<AHandgun>(HandgunClass);
    Handgun->AttachToComponent(GetMesh(), FAttachmentTransformRules::KeepRelativeTransform, TEXT("WeaponSocket"));
    Handgun->SetOwner(this);
    
    
}

// Called every frame
void AMainCharacter::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);
    //printHealth();

}

// Called to bind functionality to input
void AMainCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
    Super::SetupPlayerInputComponent(PlayerInputComponent);

    //Set up movement bindings.
    PlayerInputComponent->BindAxis("MoveForward", this, &AMainCharacter::MoveForward);
    PlayerInputComponent->BindAxis("MoveRight", this, &AMainCharacter::MoveRight);

    //Set up Look Bindings
    PlayerInputComponent->BindAxis("Turn", this, &AMainCharacter::AddControllerYawInput);
    PlayerInputComponent->BindAxis("LookUp", this, &AMainCharacter::AddControllerPitchInput);

    //Setup Weapon Shooting
    PlayerInputComponent->BindAction(TEXT("Fire"), EInputEvent::IE_Pressed, this, &AMainCharacter::Shoot);
    PlayerInputComponent->BindAction(TEXT("printHealth"), EInputEvent::IE_Pressed, this, &AMainCharacter::printHealth);

}

void AMainCharacter::Shoot()
{
    Handgun->Shoot();
}

void AMainCharacter::printHealth()
{
    GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Green, FString::Printf(TEXT("[MainCharacter DEBUG] - Current Health: %f"), currentHealth));
}

float AMainCharacter::TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, AActor* DamageCauser)
{

    float DamageToApply = Super::TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser);
    DamageToApply = FMath::Min(currentHealth, DamageToApply);
    currentHealth -= DamageToApply;

    GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Red, FString::Printf(TEXT("Health Remaining: %f"), currentHealth));
    if (currentHealth <= 0)
    {
        GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Red, TEXT("You're Dead!"));
    }

    return DamageAmount;
}

void AMainCharacter::MoveForward(float value)
{
    //Find out which way is "forward" and reocrd that the player wants to move that way
    FVector Direction = FRotationMatrix(Controller->GetControlRotation()).GetScaledAxis(EAxis::X);
    AddMovementInput(Direction, value);
}

void AMainCharacter::MoveRight(float value)
{
    //Find out which way is "right" and record that the player wants to move that way
    FVector Direction = FRotationMatrix(Controller->GetControlRotation()).GetScaledAxis(EAxis::Y);
    AddMovementInput(Direction, value);
}



但是BasicZombie.cpp中的

BoxCollider->OnComponentBeginOverlap.AddDynamic(this, &AMainCharacter::OnCollision);
在AddDynamic下有一条红线

我在用于 UE4 开发的 Discord 服务器中,但我并没有从那里获得任何帮助。

c++ unreal-engine4
1个回答
0
投票

我可以看看你的C++代码吗?您是从 UBoxComponent 调用 AddDynamic 吗? 试试这个

UPROPERTY(EditAnywhere)
     UBoxComponent* BoxCollider = nullptr;
BoxCollider = GetOwner()->FindComponentByClass<UBoxComponent>();
BoxCollider->OnComponentBeginOverlap.AddDynamic(this, &YourActor::OnCollision);

将其用作您的 OnCollision 签名

void OnCollision(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComponent, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& Hit);

另外,当我学习虚幻引擎时,我处理了很多陷阱。尝试找到虚幻引擎开发人员社区并与他们一起学习。

© www.soinside.com 2019 - 2024. All rights reserved.