I’m trying to create a projectile parent class for my game that can then be repurposed with different data assets to create different behavior patterns. Currently, the object is composed of a Capsule Component and a child Static Mesh Component (along with some other extra things like a projectile movement component and a custom damage handler).
I’m trying to bind On Component Hit for the Capsule Component using Add Dynamic, but either the hit is not being registered, or the event is not being bound. Initially, I was trying to bind a function in a different actor to the On Component Hit for the projectile’s capsule, and so I figured that that was the issue, but I tested doing this same thing with a function that’s native to the projectile class and the logic still doesn’t fire.
Here are the header and cpp files for the projectile:
#pragma once
#include "Components/CapsuleComponent.h"
#include "CoreMinimal.h"
#include "DamageOutbound.h"
#include "GameFramework/Actor.h"
#include "GameFramework/ProjectileMovementComponent.h"
#include "Projectile.generated.h"
UCLASS(BlueprintType)
class PROJECTSPIRE_API UProjectileData : public UDataAsset
{
//Information on the projectile to be used
};
UCLASS()
class PROJECTSPIRE_API AProjectile : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AProjectile();
~AProjectile();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
//initialization
bool InitializeWithDataAsset(UProjectileData* dataAsset, FVector fireDirection, AActor* inHandler);
//collision
void OnCanisterHit(UPrimitiveComponent* hitComp, AActor* otherActor, UPrimitiveComponent* otherComp, FVector normalImpulse, const FHitResult& hit);
private:
AActor* handler;
//projectile components to add by default
UCapsuleComponent* capsuleComponent;
UDamageOutbound* damageOut;
UProjectileMovementComponent* projectileMovement;
UStaticMeshComponent* staticMesh;
};
#include "Projectile.h"
// Sets default values
AProjectile::AProjectile()
{
// 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;
//spawn in and set up hierarchy of components
capsuleComponent = CreateDefaultSubobject<UCapsuleComponent>("Capsule", true);
SetRootComponent(capsuleComponent);
capsuleComponent->SetCollisionResponseToAllChannels(ECR_Block);
capsuleComponent->SetCollisionObjectType(ECC_WorldDynamic);
capsuleComponent->SetGenerateOverlapEvents(false);
staticMesh = CreateDefaultSubobject<UStaticMeshComponent>("Mesh", true);
staticMesh->SetupAttachment(capsuleComponent);
staticMesh->SetCollisionResponseToAllChannels(ECR_Ignore);
//add in additional components
damageOut = CreateDefaultSubobject<UDamageOutbound>("Damage Out", true);
projectileMovement = CreateDefaultSubobject<UProjectileMovementComponent>("Projectile", true);
projectileMovement->Velocity = FVector(0,0,0);
projectileMovement->ProjectileGravityScale = 0;
}
AProjectile::~AProjectile()
{
//...
}
// Called when the game starts or when spawned
void AProjectile::BeginPlay()
{
Super::BeginPlay();
capsuleComponent->OnComponentHit.AddDynamic(this, &AProjectile::OnCanisterHit);
}
// Called every frame
void AProjectile::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
//Pre: data to use in initializing this projectile
//Post: whether or not it could be initialized
//Purpose: setup a projectile to be used in the world with a data asset
bool AProjectile::InitializeWithDataAsset(UProjectileData* dataAsset, FVector fireDirection, AActor* inHandler)
{
//...
}
void AProjectile::OnCanisterHit(UPrimitiveComponent* hitComp, AActor* otherActor, UPrimitiveComponent* otherComp, FVector normalImpulse, const FHitResult& hit)
{
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Green, TEXT("HIT!"));
}
For testing purposes, I’m just binding this event in the AProjectile class in BeginPlay for the moment. The projectile collides with objects in the way that’s expected (i.e. it’s blocked by all other objects). However, hitting any other objects does not produce the “HIT!” text. Any help would be greatly appreciated, thanks in advance!