Having a really hard time with getting overlap collision to detect (Paper2D)

I’ve been working on a new project that I’m trying to make a top-down vertical shooter, and I’ve run into some major challenges with getting my projectiles to recognize when they overlap with an enemy.

I have two classes of objects - one projectile and one enemy, that have flipbook components as their root components along with an attached (but invisible) sprite component used to handle collision. I have two custom object collision channels set up (FriendlyProjectile, Enemies), and I can visually confirm that the sprite components assigned to the collision items appear on screen and that they overlap each other, but I don’t think the event is occurring.

I’ve tried to troubleshoot through a number of common problems that I think I’ve confirmed are not the issue:

  • All of the actors in the game are set on a Z axis of 0, with a roll of 90, so they’re connecting on the same plane. The collision geometry on the sprites also has a thickness of 10.0, so there shouldn’t be an issue with overlap not occurring.

  • In the collision sprite items, I have the Collision Presets set to Enemies and FriendlyProjectiles respectively, and those presets are set to overlap with each other. I also tested during runtime by having the sprite components return the ECollisionResponse, and it came back with Overlap.

  • I’ve also confirmed during runtime that the GenerateOverlapEvents is set to true on both sprite components, that collision is enabled.

This is the header file code I have for the projectile class:

public:

// Visual Asset Representation
	UPaperSpriteComponent *StandardCannonBoltSpriteComponent;
	UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Standard Cannon Bolt")
	UPaperSprite *StandardCannonBoltSprite;

	// Collision Management
	UPaperSpriteComponent *CollisionSpriteComponent;
	UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Collision Sprite")
	UPaperSprite *CollisionSprite;

protected:

UFUNCTION()
	void OverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
	UFUNCTION()
	void OverlapEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);

And here is the CPP file for the projectile class:

AStandardCannonBolt::AStandardCannonBolt()
{
	PrimaryActorTick.bCanEverTick = true;

	StandardCannonBoltSpriteComponent = CreateDefaultSubobject<UPaperSpriteComponent>(TEXT("Standard Cannon Bolt Sprite"));
	RootComponent = StandardCannonBoltSpriteComponent;
	CollisionSpriteComponent = CreateDefaultSubobject<UPaperSpriteComponent>(TEXT("Collision Sprite"));
	CollisionSpriteComponent->SetupAttachment(RootComponent);
}

void AStandardCannonBolt::BeginPlay()
{
	Super::BeginPlay();

	StandardCannonBoltSpriteComponent->SetSprite(StandardCannonBoltSprite);
	CollisionSpriteComponent->SetCollisionProfileName("FriendlyProjectile", true);
	CollisionSpriteComponent->SetGenerateOverlapEvents(true);
	CollisionSpriteComponent->SetSprite(CollisionSprite);
	CollisionSpriteComponent->OnComponentBeginOverlap.AddDynamic(this, &AStandardCannonBolt::OverlapBegin);
	CollisionSpriteComponent->OnComponentEndOverlap.AddDynamic(this, &AStandardCannonBolt::OverlapEnd);
	FLinearColor CollisionVisual = CollisionSpriteComponent->GetSpriteColor();
	CollisionVisual.A = 0;
	CollisionSpriteComponent->SetSpriteColor(CollisionVisual);
}

void AStandardCannonBolt::OverlapBegin(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	UE_LOG(LogTemp, Warning, TEXT("Something is happening!"));
	UE_LOG(LogTemp, Warning, TEXT("%s"), *OtherComp->GetName());
}

void AStandardCannonBolt::OverlapEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{

}

And here is the header file for the enemy class:

public:

// Visual Asset Representation
	UPaperFlipbookComponent *FlipbookComponent;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Animations")
	UPaperFlipbook *StaticAnimation;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Animations")
	UPaperFlipbook *DeathAnimation;
	
	// Collision Management
	UPaperSpriteComponent *CollisionSpriteComponent;
	UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Collision Sprite")
	UPaperSprite *CollisionSprite;

protected:

	UFUNCTION()
	void OverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
	UFUNCTION()
	void OverlapEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);

Finally, here is the relevant stuff from the CPP file for the enemy class:

AEnemy_Fodder::AEnemy_Fodder()
{
	PrimaryActorTick.bCanEverTick = true;

	FlipbookComponent = CreateDefaultSubobject<UPaperFlipbookComponent>(TEXT("Flipbook"));
	RootComponent = FlipbookComponent;
	CollisionSpriteComponent = CreateDefaultSubobject<UPaperSpriteComponent>(TEXT("Collision Sprite"));
	CollisionSpriteComponent->SetupAttachment(RootComponent);
}

void AEnemy_Fodder::BeginPlay()
{
	Super::BeginPlay();

	FlipbookComponent->SetFlipbook(StaticAnimation);
	CollisionSpriteComponent->SetCollisionProfileName("Enemies", true);
	CollisionSpriteComponent->SetGenerateOverlapEvents(true);
	CollisionSpriteComponent->SetSprite(CollisionSprite);
	CollisionSpriteComponent->OnComponentBeginOverlap.AddDynamic(this, &AEnemy_Fodder::OverlapBegin);
	CollisionSpriteComponent->OnComponentEndOverlap.AddDynamic(this, &AEnemy_Fodder::OverlapEnd);
	FLinearColor CollisionVisual = CollisionSpriteComponent->GetSpriteColor();
	CollisionVisual.A = 0;
	CollisionSpriteComponent->SetSpriteColor(CollisionVisual);
}

void AEnemy_Fodder::OverlapBegin(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	UE_LOG(LogTemp, Warning, TEXT("Something is happening!"));
	UE_LOG(LogTemp, Warning, TEXT("%s"), *OtherComp->GetName());
}

void AEnemy_Fodder::OverlapEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{

}

A couple of last minute notes from trying to solve it myself-

  • In the BeginPlay() function, I set the CollisionProfileName because I noticed, even with the sprite assets edited to show the preset I wanted, the CollisionProfileName at runtime was ‘BlockAllDynamic’.

  • At one point, I printed the constant to show the number of overlap events occurring during the entire game and saw that it did not increment up when the objects passed by each other. It has me pretty certain that the problem is the overlap event is not being recognized.

  • I briefly had an overlap event occurring where the projectile was hitting itself. It turned out I hadn’t set the root component sprite to NoCollision yet, and after changing it, I no longer experience that. But it did show the projectile actually was checking collision to some extent.

Appreciate any and all help I can get on this, as it has me just stuck.