Add Enemy Batching
This commit is contained in:
parent
2ad6b53ab3
commit
3a729caab0
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
AEnemyCharacter::AEnemyCharacter(const FObjectInitializer& ObjectInitializer)
|
AEnemyCharacter::AEnemyCharacter(const FObjectInitializer& ObjectInitializer)
|
||||||
{
|
{
|
||||||
|
ObjectPoolComponent = CreateDefaultSubobject<UObjectPoolComponent>(TEXT("Object Pool Component"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AEnemyCharacter::BeginPlay()
|
void AEnemyCharacter::BeginPlay()
|
||||||
|
@ -15,6 +16,8 @@ void AEnemyCharacter::BeginPlay()
|
||||||
Super::BeginPlay();
|
Super::BeginPlay();
|
||||||
GetHealthComponent()->OnDamaged.BindUFunction(this, "OnDamaged");
|
GetHealthComponent()->OnDamaged.BindUFunction(this, "OnDamaged");
|
||||||
GetHealthComponent()->OnDeath.BindUFunction(this, "OnDeath");
|
GetHealthComponent()->OnDeath.BindUFunction(this, "OnDeath");
|
||||||
|
|
||||||
|
ObjectPoolComponent->OnRetrieve.BindUFunction(this, "ResetHealth");
|
||||||
}
|
}
|
||||||
|
|
||||||
void AEnemyCharacter::Tick(float DeltaTime)
|
void AEnemyCharacter::Tick(float DeltaTime)
|
||||||
|
@ -33,17 +36,20 @@ void AEnemyCharacter::OnDamaged()
|
||||||
|
|
||||||
void AEnemyCharacter::OnDeath()
|
void AEnemyCharacter::OnDeath()
|
||||||
{
|
{
|
||||||
//if (IsValid(EXPPickupTemplate))
|
FActorSpawnParameters actorSpawnParameters;
|
||||||
//{
|
actorSpawnParameters.Owner = this;
|
||||||
FActorSpawnParameters actorSpawnParameters;
|
actorSpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
|
||||||
actorSpawnParameters.Owner = this;
|
actorSpawnParameters.TransformScaleMethod = ESpawnActorScaleMethod::MultiplyWithRoot;
|
||||||
actorSpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
|
|
||||||
actorSpawnParameters.TransformScaleMethod = ESpawnActorScaleMethod::MultiplyWithRoot;
|
|
||||||
|
|
||||||
GetWorld()->SpawnActor<AEXPPickup>(EXPPickupTemplate, GetActorLocation(), FRotator::ZeroRotator,
|
GetWorld()->SpawnActor<AEXPPickup>(EXPPickupTemplate, GetActorLocation(), FRotator::ZeroRotator,
|
||||||
actorSpawnParameters);
|
actorSpawnParameters);
|
||||||
|
|
||||||
AVampireGameMode* gamemode = Cast<AVampireGameMode>(UGameplayStatics::GetGameMode(GetWorld()));
|
AVampireGameMode* gamemode = Cast<AVampireGameMode>(UGameplayStatics::GetGameMode(GetWorld()));
|
||||||
gamemode->IncrementEnemyDeathCount();
|
gamemode->IncrementEnemyDeathCount();
|
||||||
//}
|
gamemode->GetEnemyObjectPoolManager()->ReturnObject(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AEnemyCharacter::ResetHealth()
|
||||||
|
{
|
||||||
|
GetHealthComponent()->ResetHealth();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include "CoreMinimal.h"
|
#include "CoreMinimal.h"
|
||||||
#include "EXPPickup.h"
|
#include "EXPPickup.h"
|
||||||
|
#include "ObjectPoolComponent.h"
|
||||||
#include "VampireCharacter.h"
|
#include "VampireCharacter.h"
|
||||||
#include "BehaviorTree/BehaviorTree.h"
|
#include "BehaviorTree/BehaviorTree.h"
|
||||||
#include "EnemyCharacter.generated.h"
|
#include "EnemyCharacter.generated.h"
|
||||||
|
@ -21,10 +22,11 @@ public:
|
||||||
TSubclassOf<AEXPPickup> EXPPickupTemplate = nullptr;
|
TSubclassOf<AEXPPickup> EXPPickupTemplate = nullptr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
UPROPERTY(EditDefaultsOnly, Meta = (AllowPrivateAccess = "true"))
|
UPROPERTY(EditDefaultsOnly, Meta = (AllowPrivateAccess = "true"))
|
||||||
UBehaviorTree* BehaviorTree = nullptr;
|
UBehaviorTree* BehaviorTree = nullptr;
|
||||||
|
|
||||||
|
UObjectPoolComponent* ObjectPoolComponent = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AEnemyCharacter(const FObjectInitializer& ObjectInitializer);
|
AEnemyCharacter(const FObjectInitializer& ObjectInitializer);
|
||||||
|
|
||||||
|
@ -41,4 +43,8 @@ public:
|
||||||
|
|
||||||
UFUNCTION()
|
UFUNCTION()
|
||||||
virtual void OnDeath();
|
virtual void OnDeath();
|
||||||
|
|
||||||
|
private:
|
||||||
|
UFUNCTION()
|
||||||
|
void ResetHealth();
|
||||||
};
|
};
|
||||||
|
|
|
@ -70,6 +70,7 @@ void UHealthComponent::SetCurrentHealth(float value)
|
||||||
void UHealthComponent::ResetHealth()
|
void UHealthComponent::ResetHealth()
|
||||||
{
|
{
|
||||||
CurrentHealth = MaxHealth;
|
CurrentHealth = MaxHealth;
|
||||||
|
IsDead = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UHealthComponent::RecoverHealth(float value)
|
void UHealthComponent::RecoverHealth(float value)
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
// Fill out your copyright notice in the Description page of Project Settings.
|
||||||
|
|
||||||
|
|
||||||
|
#include "ObjectPoolComponent.h"
|
||||||
|
|
|
@ -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;
|
||||||
|
};
|
|
@ -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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
};
|
|
@ -61,7 +61,7 @@ void AVampireAIController::OnDeath(FDamageInfo info)
|
||||||
{
|
{
|
||||||
// TODO: Do stuff here
|
// TODO: Do stuff here
|
||||||
EnemyCharacter->OnDeath();
|
EnemyCharacter->OnDeath();
|
||||||
EnemyCharacter->DetachFromControllerPendingDestroy();
|
/*EnemyCharacter->DetachFromControllerPendingDestroy();
|
||||||
EnemyCharacter->GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision);
|
EnemyCharacter->GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision);
|
||||||
EnemyCharacter->GetCapsuleComponent()->SetCollisionResponseToAllChannels(ECR_Ignore);
|
EnemyCharacter->GetCapsuleComponent()->SetCollisionResponseToAllChannels(ECR_Ignore);
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ void AVampireAIController::OnDeath(FDamageInfo info)
|
||||||
characterMovementComponent->SetComponentTickEnabled(false);
|
characterMovementComponent->SetComponentTickEnabled(false);
|
||||||
}
|
}
|
||||||
GetWorldTimerManager().ClearTimer(PawnMoveToTimerHandle);
|
GetWorldTimerManager().ClearTimer(PawnMoveToTimerHandle);
|
||||||
EnemyCharacter->SetLifeSpan(0.1f);
|
EnemyCharacter->SetLifeSpan(0.1f);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void AVampireAIController::PawnMoveTo()
|
void AVampireAIController::PawnMoveTo()
|
||||||
|
|
|
@ -65,13 +65,29 @@ void AVampireGameMode::SpawnEnemy()
|
||||||
FActorSpawnParameters SpawnParameters;
|
FActorSpawnParameters SpawnParameters;
|
||||||
SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
|
SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
|
||||||
|
|
||||||
AEnemyCharacter* Actor = GetWorld()->SpawnActor<AEnemyCharacter>(EnemyTemplate, Transform, SpawnParameters);
|
if (AActor* object = GetEnemyObjectPoolManager()->GetObject())
|
||||||
float CapsuleRadius = Actor->GetCapsuleComponent()->GetScaledCapsuleRadius();
|
{
|
||||||
FVector Direction = SpawnLocation - PlayerCharacter->GetActorLocation();
|
AEnemyCharacter* Actor = Cast<AEnemyCharacter>(object);
|
||||||
Direction.Normalize();
|
Actor->SetActorTransform(Transform);
|
||||||
Direction *= CapsuleRadius;
|
float CapsuleRadius = Actor->GetCapsuleComponent()->GetScaledCapsuleRadius();
|
||||||
Actor->SetActorLocation(SpawnLocation + Direction);
|
FVector Direction = SpawnLocation - PlayerCharacter->GetActorLocation();
|
||||||
Actor->SpawnDefaultController();
|
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()
|
void AVampireGameMode::IncrementEnemyDeathCount()
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include "CoreMinimal.h"
|
#include "CoreMinimal.h"
|
||||||
#include "EnemyCharacter.h"
|
#include "EnemyCharacter.h"
|
||||||
|
#include "ObjectPoolManager.h"
|
||||||
#include "PlayerCharacter.h"
|
#include "PlayerCharacter.h"
|
||||||
#include "VampirePlayerController.h"
|
#include "VampirePlayerController.h"
|
||||||
#include "GameFramework/GameMode.h"
|
#include "GameFramework/GameMode.h"
|
||||||
|
@ -30,6 +31,8 @@ private:
|
||||||
|
|
||||||
int EnemyDeathCount = 0;
|
int EnemyDeathCount = 0;
|
||||||
|
|
||||||
|
AObjectPoolManager* EnemyObjectPoolManager = nullptr;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void BeginPlay() override;
|
virtual void BeginPlay() override;
|
||||||
|
|
||||||
|
@ -40,8 +43,9 @@ public:
|
||||||
UFUNCTION()
|
UFUNCTION()
|
||||||
void IncrementEnemyDeathCount();
|
void IncrementEnemyDeathCount();
|
||||||
|
|
||||||
protected:
|
AObjectPoolManager* GetEnemyObjectPoolManager();
|
||||||
|
|
||||||
|
protected:
|
||||||
UFUNCTION()
|
UFUNCTION()
|
||||||
void SpawnEnemy();
|
void SpawnEnemy();
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue