I’ve been following the Tanks vs. Zombies C++ tutorial and have run into a problem that I’m having trouble fixing.
When firing a missile, the missile should time out after 1 second and explode or collide with a zombie, deal damage once and then explode. The explosion animation is a Paper2D flipbook. However, my missiles are still active seemingly until the flipbook is finished, meaning that the missiles still deal damage.
Please let me know if you need more information. Any help is appreciated, thank you.
Missile.cpp:
[SPOILER]
// Fill out your copyright notice in the Description page of Project Settings.
#include "Missile.h"
#include "Public/TimerManager.h"
#include "Public/WorldCollision.h"
#include "DamageInterface.h"
#include "Engine/World.h"
// Sets default values
AMissile::AMissile()
{
// 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;
Speed = 200.0f;
Radius = 20.0f;
DirectDamage = 5;
}
// Called when the game starts or when spawned
void AMissile::BeginPlay()
{
Super::BeginPlay();
GetWorldTimerManager().SetTimer(ExplodeTimerHandle, this, &AMissile::Explode, 1.0f);
}
// Called every frame
void AMissile::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
FVector Loc = GetActorLocation();
FVector DesiredEndLoc = Loc + ((DeltaTime * Speed) * GetTransform().GetUnitAxis(EAxis::X));
if (UWorld* World = GetWorld())
{
FHitResult OutHit;
FCollisionShape CollisionShape;
CollisionShape.SetCapsule(Radius, 200.0f);
if (World->SweepSingleByProfile(OutHit, Loc, DesiredEndLoc, FQuat::Identity, MovementCollisionProfile, CollisionShape))
{
SetActorLocation(OutHit.Location);
if (IDamageInterface* DamageActor = Cast<IDamageInterface>(OutHit.Actor.Get()))
{
DamageActor->RecieveDamage(DirectDamage);
}
Explode();
}
else
{
SetActorLocation(DesiredEndLoc);
}
}
}
void AMissile::Explode()
{
GetWorldTimerManager().ClearTimer(ExplodeTimerHandle);
SetActorEnableCollision(false);
OnExplode();
}
void AMissile::OnExplode_Implementation()
{
Destroy();
}
[/SPOILER]
Missile.h
[SPOILER]
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Missile.generated.h"
UCLASS()
class TANKS_API AMissile : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AMissile();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
/** How fast the missile travels. */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Projectile")
float Speed;
/** This missile's radius for collisions. */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Projectile")
float Radius;
/** How much damage the missile does. */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Projectile")
int32 DirectDamage;
/** Describes what this missle hits. */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Projectile")
FName MovementCollisionProfile;
protected:
void Explode();
FTimerHandle ExplodeTimerHandle;
/** What to do when the projectile explodes. The base version just destroys the projectile. */
UFUNCTION(BlueprintNativeEvent, Category = "Projectile")
void OnExplode();
virtual void OnExplode_Implementation();
};
[/SPOILER]
Collision Profile:
Zombie taking 100 hits:
Zombie walking into exploded missile: