UE5--014--DodgeballFunctionLibrary--HealthInterface--HealthComponent--LookAtActorComponent


1. DodgeballFunctionLibrary

1.1 DodgeballFunctionLibrary.h


#pragma once

#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "DodgeballFunctionLibrary.generated.h"

/**
 * 
 */
UCLASS()
class C005DODGEBALL_API UDodgeballFunctionLibrary : public UBlueprintFunctionLibrary
{
    GENERATED_BODY()
    
public:
    static bool CanSeeActor(const UWorld* World, FVector Location, const AActor* TargetActor, TArray<const AActor*> IgnoreActors = TArray<const    AActor*>());
};


1.2 DodgeballFunctionLibrary.cpp


#include "DodgeballFunctionLibrary.h"
#include "Engine/World.h"
#include "DrawDebugHelpers.h"
#include "CollisionQueryParams.h"

bool UDodgeballFunctionLibrary::CanSeeActor(const UWorld* World, FVector Location, const AActor* TargetActor, TArray<const AActor*> IgnoreActors) {
    // Store the results of the Line Trace
    FHitResult Hit;
    // Where the Line Trace starts and ends
    FVector Start = Location;
    FVector End = TargetActor->GetActorLocation();
    FCollisionQueryParams QueryParams;
    // Ignore the actors specified
    QueryParams.AddIgnoredActors(IgnoreActors);
    // The trace channel we want to compare against
    ECollisionChannel Channel = ECollisionChannel::ECC_Visibility;
    // Execute the Line Trace
    World->LineTraceSingleByChannel(Hit, Start, End, Channel,QueryParams);
    // Show the Line Trace inside the game
    DrawDebugLine(World, Start, End, FColor::Red);
    //
    return !Hit.bBlockingHit;
}


2. HealthInterface

2.1 HealthInterface.h


#pragma once

#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "HealthInterface.generated.h"

// This class does not need to be modified.
UINTERFACE(MinimalAPI)
class UHealthInterface : public UInterface
{
    GENERATED_BODY()
};

/**
 * 
 */
class C005DODGEBALL_API IHealthInterface
{
    GENERATED_BODY()

    // Add interface functions to this class. This is the class that will be inherited to implement this interface.
public:

    UFUNCTION(BlueprintNativeEvent, Category = Health)
    void OnDeath();
    virtual void OnDeath_Implementation() = 0;

    UFUNCTION(BlueprintNativeEvent, Category = Health)
    void OnTakeDamage();
    virtual void OnTakeDamage_Implementation() = 0;

};


2.2 HealthInterface.cpp


#include "HealthInterface.h"

// Add default functionality here for any IHealthInterface functions that are not pure virtual.


3. HealthComponent

3.1 HealthComponent.h


#pragma once

#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "HealthComponent.generated.h"


UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class C005DODGEBALL_API UHealthComponent : public UActorComponent
{
    GENERATED_BODY()

public:    
    // Sets default values for this component's properties
    UHealthComponent();

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

    // The Owner's initial and current amount health points
    UPROPERTY(EditDefaultsOnly, Category = Health)
    float Health = 100.f;


public:    
    // Called every frame
    virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;

    // Take health points from its Owner
    void LoseHealth(float Amount);

            
    FORCEINLINE float GetHealthPercent() const {
        return Health /    100.f;
    }

};


3.2 HealthComponent.cpp


#include "HealthComponent.h"
#include "Kismet/KismetSystemLibrary.h"
// With this line
#include "HealthInterface.h"
#include "GameFramework/Actor.h"

// Sets default values for this component's properties
UHealthComponent::UHealthComponent()
{
    // Set this component to be initialized when the game starts, and to be ticked every frame.  You can turn these features
    // off to improve performance if you don't need them.
    PrimaryComponentTick.bCanEverTick = false;
    // ...
}


// Called when the game starts
void UHealthComponent::BeginPlay()
{
    Super::BeginPlay();

    // ...
    
}


// Called every frame
void UHealthComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
    Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

    // ...
}

void UHealthComponent::LoseHealth(float Amount)
{
    Health -= Amount;

    if (GetOwner()->Implements<UHealthInterface>())
    {
        IHealthInterface::Execute_OnTakeDamage(GetOwner());
    }

    if (Health <= 0.f)
    {
        Health = 0.f;
        if (1 == 0) {
            UKismetSystemLibrary::QuitGame(this, nullptr, EQuitPreference::Quit, true);
        }
        else {
            if (GetOwner()->Implements<UHealthInterface>())
            {
                IHealthInterface::Execute_OnDeath(GetOwner());
            }
        }
    }
}


4. LookAtActorComponent

4.1 LookAtActorComponent.h


#pragma once

#include "CoreMinimal.h"
#include "Components/SceneComponent.h"
#include "LookAtActorComponent.generated.h"


UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class C005DODGEBALL_API ULookAtActorComponent : public USceneComponent
{
    GENERATED_BODY()

public:    
    // Sets default values for this component's properties
    ULookAtActorComponent();

    FORCEINLINE void SetTarget(class AActor* NewTarget) {
        TargetActor = NewTarget; 
    }

    FORCEINLINE  bool CanSeeTarget() const  {
        return bCanSeeTarget;
    }

    

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

    class AActor* TargetActor;

    bool bCanSeeTarget = false;

    bool LookAtActor();

public:    
    // Called every frame
    virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;

        
};


4.2 LookAtActorComponent.cpp

#include "LookAtActorComponent.h"
#include "GameFramework/Actor.h"
#include "Kismet/KismetMathLibrary.h"
#include "DodgeballFunctionLibrary.h"

// Sets default values for this component's properties
ULookAtActorComponent::ULookAtActorComponent()
{
    // Set this component to be initialized when the game starts, and to be ticked every frame.  You can turn these features
    // off to improve performance if you don't need them.
    PrimaryComponentTick.bCanEverTick = true;

    // ...
}


// Called when the game starts
void ULookAtActorComponent::BeginPlay()
{
    Super::BeginPlay();

    // ...

}


// Called every frame
void ULookAtActorComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
    Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

    // ...
    bCanSeeTarget = LookAtActor();
}

bool ULookAtActorComponent::LookAtActor()
{
    if (TargetActor == nullptr) return false;
    TArray<const AActor*> IgnoreActors = { GetOwner(),    TargetActor };
    if (UDodgeballFunctionLibrary::CanSeeActor(GetWorld(), GetComponentLocation(), TargetActor, IgnoreActors))
    {
        FVector Start = GetOwner()->GetActorLocation();
        FVector End = TargetActor->GetActorLocation();
        // Calculate the necessary rotation for the Start point to face the End point
        FRotator LookAtRotation = UKismetMathLibrary::FindLookAtRotation(Start, End);
        //Set the enemy’s rotation to that rotation        
        GetOwner()->SetActorRotation(LookAtRotation);
        return true;
    }
    return false;

}
posted @ 2025-04-05 21:10  ParamousGIS  阅读(23)  评论(0)    收藏  举报