Add Enemy Batching

This commit is contained in:
baz 2024-08-22 22:11:24 +01:00
parent 2ad6b53ab3
commit 3a729caab0
10 changed files with 187 additions and 29 deletions

View File

@ -8,6 +8,7 @@
AEnemyCharacter::AEnemyCharacter(const FObjectInitializer& ObjectInitializer)
{
ObjectPoolComponent = CreateDefaultSubobject<UObjectPoolComponent>(TEXT("Object Pool Component"));
}
void AEnemyCharacter::BeginPlay()
@ -15,6 +16,8 @@ void AEnemyCharacter::BeginPlay()
Super::BeginPlay();
GetHealthComponent()->OnDamaged.BindUFunction(this, "OnDamaged");
GetHealthComponent()->OnDeath.BindUFunction(this, "OnDeath");
ObjectPoolComponent->OnRetrieve.BindUFunction(this, "ResetHealth");
}
void AEnemyCharacter::Tick(float DeltaTime)
@ -33,17 +36,20 @@ void AEnemyCharacter::OnDamaged()
void AEnemyCharacter::OnDeath()
{
//if (IsValid(EXPPickupTemplate))
//{
FActorSpawnParameters actorSpawnParameters;
actorSpawnParameters.Owner = this;
actorSpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
actorSpawnParameters.TransformScaleMethod = ESpawnActorScaleMethod::MultiplyWithRoot;
FActorSpawnParameters actorSpawnParameters;
actorSpawnParameters.Owner = this;
actorSpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
actorSpawnParameters.TransformScaleMethod = ESpawnActorScaleMethod::MultiplyWithRoot;
GetWorld()->SpawnActor<AEXPPickup>(EXPPickupTemplate, GetActorLocation(), FRotator::ZeroRotator,
actorSpawnParameters);
GetWorld()->SpawnActor<AEXPPickup>(EXPPickupTemplate, GetActorLocation(), FRotator::ZeroRotator,
actorSpawnParameters);
AVampireGameMode* gamemode = Cast<AVampireGameMode>(UGameplayStatics::GetGameMode(GetWorld()));
gamemode->IncrementEnemyDeathCount();
//}
AVampireGameMode* gamemode = Cast<AVampireGameMode>(UGameplayStatics::GetGameMode(GetWorld()));
gamemode->IncrementEnemyDeathCount();
gamemode->GetEnemyObjectPoolManager()->ReturnObject(this);
}
void AEnemyCharacter::ResetHealth()
{
GetHealthComponent()->ResetHealth();
}

View File

@ -4,6 +4,7 @@
#include "CoreMinimal.h"
#include "EXPPickup.h"
#include "ObjectPoolComponent.h"
#include "VampireCharacter.h"
#include "BehaviorTree/BehaviorTree.h"
#include "EnemyCharacter.generated.h"
@ -19,12 +20,13 @@ class VAMPIRES_API AEnemyCharacter : public AVampireCharacter
public:
UPROPERTY(EditDefaultsOnly)
TSubclassOf<AEXPPickup> EXPPickupTemplate = nullptr;
private:
private:
UPROPERTY(EditDefaultsOnly, Meta = (AllowPrivateAccess = "true"))
UBehaviorTree* BehaviorTree = nullptr;
UObjectPoolComponent* ObjectPoolComponent = nullptr;
public:
AEnemyCharacter(const FObjectInitializer& ObjectInitializer);
@ -41,4 +43,8 @@ public:
UFUNCTION()
virtual void OnDeath();
private:
UFUNCTION()
void ResetHealth();
};

View File

@ -70,6 +70,7 @@ void UHealthComponent::SetCurrentHealth(float value)
void UHealthComponent::ResetHealth()
{
CurrentHealth = MaxHealth;
IsDead = false;
}
void UHealthComponent::RecoverHealth(float value)
@ -105,4 +106,4 @@ void UHealthComponent::BeginPlay()
Super::BeginPlay();
ResetHealth();
}
}

View File

@ -0,0 +1,5 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "ObjectPoolComponent.h"

View File

@ -0,0 +1,21 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "ObjectPoolComponent.generated.h"
DECLARE_DELEGATE(FOnRetrieve)
DECLARE_DELEGATE(FOnReturn)
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class VAMPIRES_API UObjectPoolComponent : public UActorComponent
{
GENERATED_BODY()
public:
FOnRetrieve OnRetrieve;
FOnReturn OnReturn;
};

View File

@ -0,0 +1,69 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "ObjectPoolManager.h"
#include "ObjectPoolComponent.h"
// Called when the game starts or when spawned
void AObjectPoolManager::BeginPlay()
{
Super::BeginPlay();
}
void AObjectPoolManager::InitializeObjectPool(TSubclassOf<AActor> Object, const int InitialObjectPoolSize)
{
for (int i = 0; i < InitialObjectPoolSize; i++)
{
AActor* object = GetWorld()->SpawnActor<AActor>(Object);
SetObjectStatus(false, object);
ObjectPool.Add(object);
}
}
void AObjectPoolManager::InitializeObjectPool(UClass* Object, int InitialObjectPoolSize)
{
for (int i = 0; i < InitialObjectPoolSize; i++)
{
AActor* object = GetWorld()->SpawnActor<AActor>(Object);
SetObjectStatus(false, object);
ObjectPool.Add(object);
}
}
AActor* AObjectPoolManager::GetObject()
{
for (AActor* object : ObjectPool)
{
if (object->IsHidden())
{
SetObjectStatus(true, object);
if (UObjectPoolComponent* objectPoolComponent = object->GetComponentByClass<UObjectPoolComponent>())
{
objectPoolComponent->OnRetrieve.ExecuteIfBound();
}
return object;
}
}
return nullptr;
}
void AObjectPoolManager::ReturnObject(AActor* object)
{
SetObjectStatus(false, object);
if (UObjectPoolComponent* objectPoolComponent = object->GetComponentByClass<UObjectPoolComponent>())
{
objectPoolComponent->OnReturn.ExecuteIfBound();
}
}
void AObjectPoolManager::SetObjectStatus(bool enabled, AActor* object)
{
object->SetActorHiddenInGame(!enabled);
object->SetActorTickEnabled(enabled);
object->SetActorEnableCollision(enabled);
}

View File

@ -0,0 +1,30 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "ObjectPoolManager.generated.h"
UCLASS()
class VAMPIRES_API AObjectPoolManager : public AActor
{
GENERATED_BODY()
TArray<AActor*> ObjectPool = TArray<AActor*>();
public:
void InitializeObjectPool(TSubclassOf<AActor> Object, int InitialObjectPoolSize = 400);
void InitializeObjectPool(UClass* Object, int InitialObjectPoolSize = 400);
AActor* GetObject();
void ReturnObject(AActor* object);
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
private:
void SetObjectStatus(bool enabled, AActor* object);
};

View File

@ -61,7 +61,7 @@ void AVampireAIController::OnDeath(FDamageInfo info)
{
// TODO: Do stuff here
EnemyCharacter->OnDeath();
EnemyCharacter->DetachFromControllerPendingDestroy();
/*EnemyCharacter->DetachFromControllerPendingDestroy();
EnemyCharacter->GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision);
EnemyCharacter->GetCapsuleComponent()->SetCollisionResponseToAllChannels(ECR_Ignore);
@ -72,7 +72,7 @@ void AVampireAIController::OnDeath(FDamageInfo info)
characterMovementComponent->SetComponentTickEnabled(false);
}
GetWorldTimerManager().ClearTimer(PawnMoveToTimerHandle);
EnemyCharacter->SetLifeSpan(0.1f);
EnemyCharacter->SetLifeSpan(0.1f);*/
}
void AVampireAIController::PawnMoveTo()

View File

@ -57,21 +57,37 @@ void AVampireGameMode::SpawnEnemy()
UE_LOG(LogTemp, Warning, TEXT("Something broke"));
break;
}
SpawnLocation.Z = PlayerCharacter->GetActorLocation().Z;
FTransform Transform;
Transform.SetLocation(SpawnLocation);
FActorSpawnParameters SpawnParameters;
SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
AEnemyCharacter* Actor = GetWorld()->SpawnActor<AEnemyCharacter>(EnemyTemplate, Transform, SpawnParameters);
float CapsuleRadius = Actor->GetCapsuleComponent()->GetScaledCapsuleRadius();
FVector Direction = SpawnLocation - PlayerCharacter->GetActorLocation();
Direction.Normalize();
Direction *= CapsuleRadius;
Actor->SetActorLocation(SpawnLocation + Direction);
Actor->SpawnDefaultController();
if (AActor* object = GetEnemyObjectPoolManager()->GetObject())
{
AEnemyCharacter* Actor = Cast<AEnemyCharacter>(object);
Actor->SetActorTransform(Transform);
float CapsuleRadius = Actor->GetCapsuleComponent()->GetScaledCapsuleRadius();
FVector Direction = SpawnLocation - PlayerCharacter->GetActorLocation();
Direction.Normalize();
Direction *= CapsuleRadius;
Actor->SetActorLocation(SpawnLocation + Direction);
Actor->SpawnDefaultController();
}
}
AObjectPoolManager* AVampireGameMode::GetEnemyObjectPoolManager()
{
if (EnemyObjectPoolManager == nullptr)
{
EnemyObjectPoolManager = GetWorld()->SpawnActor<AObjectPoolManager>();
TSubclassOf<AActor> enemyTemplate = EnemyTemplate;
EnemyObjectPoolManager->InitializeObjectPool(enemyTemplate);
}
return EnemyObjectPoolManager;
}
void AVampireGameMode::IncrementEnemyDeathCount()

View File

@ -4,6 +4,7 @@
#include "CoreMinimal.h"
#include "EnemyCharacter.h"
#include "ObjectPoolManager.h"
#include "PlayerCharacter.h"
#include "VampirePlayerController.h"
#include "GameFramework/GameMode.h"
@ -30,18 +31,21 @@ private:
int EnemyDeathCount = 0;
AObjectPoolManager* EnemyObjectPoolManager = nullptr;
protected:
virtual void BeginPlay() override;
public:
UFUNCTION(BlueprintCallable, BlueprintPure)
int GetEnemyDeathCount();
UFUNCTION()
void IncrementEnemyDeathCount();
AObjectPoolManager* GetEnemyObjectPoolManager();
protected:
UFUNCTION()
void SpawnEnemy();
};